<commit_before>#     Copyright 2018, <NAME>, mailto:<EMAIL>
#
#     Part of "Nuitka", an optimizing Python compiler that is compatible and
#     integrates with CPython, but also works on its own.
#
#     Licensed under the Apache License, Version 2.0 (the "License");
#     you may not use this file except in compliance with the License.
#     You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#     Unless required by applicable law or agreed to in writing, software
#     distributed under the License is distributed on an "AS IS" BASIS,
#     WITHOUT 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 . import OperatorCodes
from .CodeHelpers import generateExpressionCode
from .ErrorCodes import getErrorExitBoolCode, getErrorExitCode, getReleaseCodes


def generateComparisonExpressionCode(to_name, expression, emit, context):
    left_name = context.allocateTempName("compexpr_left")
    right_name = context.allocateTempName("compexpr_right")

    generateExpressionCode(
        to_name    = left_name,
        expression = expression.getLeft(),
        emit       = emit,
        context    = context
    )
    generateExpressionCode(
        to_name    = right_name,
        expression = expression.getRight(),
        emit       = emit,
        context    = context
    )

    comparator  = expression.getComparator()

    if comparator in OperatorCodes.containing_comparison_codes:
        needs_check = expression.getRight().mayRaiseExceptionIn(
            BaseException,
            expression.getLeft()
        )

        res_name = context.getIntResName()

        emit(
             "%s = PySequence_Contains( %s, %s );" % (
                res_name,
                right_name, # sequence goes first in the API.
                left_name
            )
        )

        getErrorExitBoolCode(
            condition     = "%s == -1" % res_name,
            release_names = (left_name, right_name),
            needs_check   = needs_check,
            emit          = emit,
            context       = context
        )

        emit(
            to_name.getCType().getAssignmentCodeFromBoolCondition(
                to_name   = to_name,
                condition = "%s == %d" % (
                    res_name,
                    1 if comparator == "In" else 0
                )
            )
        )<commit_msg>Ctypes: Make "is/is not" operator aware of boolean arguments.<commit_after>#     Copyright 2018, <NAME>, mailto:<EMAIL>
#
#     Part of "Nuitka", an optimizing Python compiler that is compatible and
#     integrates with CPython, but also works on its own.
#
#     Licensed under the Apache License, Version 2.0 (the "License");
#     you may not use this file except in compliance with the License.
#     You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#     Unless required by applicable law or agreed to in writing, software
#     distributed under the License is distributed on an "AS IS" BASIS,
#     WITHOUT 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.nodes.shapes.BuiltinTypeShapes import ShapeTypeBool
from nuitka.Options import isExperimental

from . import OperatorCodes
from .CodeHelpers import generateExpressionCode
from .ErrorCodes import getErrorExitBoolCode, getErrorExitCode, getReleaseCodes


def generateComparisonExpressionCode(to_name, expression, emit, context):
    # Currently high complexity, due to manual C typing and doing all
    # in one place, pylint: disable=too-many-branches,too-many-statements

    left = expression.getLeft()
    right = expression.getRight()

    comparator  = expression.getComparator()

    type_name = "PyObject *"
    if comparator in ("Is", "IsNot") and isExperimental("enabled_bool_ctype"):
        if left.getTypeShape() is ShapeTypeBool and \
           right.getTypeShape() is ShapeTypeBool:
            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.getLeft()
        )

        res_name = context.getIntResName()

        emit(
             "%s = PySequence_Contains( %s, %s );" % (
                res_name,
                right_name, # sequence goes first in the API.
                left_name
            )
        )

        getErrorExitBoolCode(
            condition     = "%s == -1" % res_name,
            release_names = (left_name, right_name),
            needs_check   = needs_check,
            emit          = emit,
            context       = context
        )

        emit(
            to_name.getCType().getAssignmentCodeFromBoolCondition(
                to_name   = to_name,
                condition = "%s == %d" % (
                    res_name,
                    1 if comparator == "In" else 0
                )
            )
        )
{'fraction_non_alphanumeric': 0.0793068977007664, 'fraction_numerical': 0.0036654448517160947, 'mean_word_length': 2.2222222222222223, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7466153', 'n_tokens_mistral': 1626, 'n_tokens_neox': 1574, 'n_words': 507}