{#     Copyright 2024, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file #}

{% set props = {"exits": {}} %}
{% from 'HelperSlotsInt.c.j2' import int_core with context %}
{% set bool_mode = target and target.type_name in ("nuitka_bool", "nbool") %}
bool BINARY_OPERATION_{{op_code}}_{{target.getHelperCodeName()}}_{{left.getHelperCodeName()}}_{{right.getHelperCodeName()}}({{ target.getVariableDecl("result") }}, {{left.getVariableDecl("operand1")}}, {{right.getVariableDecl("operand2")}}) {
    {{ left.getCheckValueCode("operand1") }}
    {{ right.getCheckValueCode("operand2") }}

    bool left_c_usable = {{left.getDualValidityCheckCode("C", "operand1")}};
    bool right_c_usable = {{right.getDualValidityCheckCode("C", "operand2")}};

    if (left_c_usable && right_c_usable) {
{% if target.isSimilarOrSameTypesAsOneOf(n_ilong_desc) %}
    // 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")}}

{% if props["fall_through_needed"] %}
{% if left.isDualType() %}
        {{left.getDualTypeEnsurePythonObjectCode("operand1")}}
        obj_result = BINARY_OPERATION_{{op_code}}_OBJECT_{{left.getDualType("Python").getHelperCodeName()}}_{{right.getDualType("C").getHelperCodeName()}}({{left.getDualTypeAccessCode("Python", "operand1")}}, {{right.getDualTypeAccessCode("C", "operand2")}});
{% else %}
        {{right.getDualTypeEnsurePythonObjectCode("operand2")}}
        obj_result = BINARY_OPERATION_{{op_code}}_OBJECT_{{left.getDualType("C").getHelperCodeName()}}_{{right.getDualType("Python").getHelperCodeName()}}({{left.getDualTypeAccessCode("C", "operand1")}}, {{right.getDualTypeAccessCode("Python", "operand2")}});
{% endif %}

        if (unlikely(result == NULL)) {
            return false;
        }

        {{ target.getAssignFromObjectExpressionCode("result", "obj_result") }}
        return true;

{% else %}
        {{ 0/0 }}
{% endif %}
{% endif %}

{% if "exit_result_ok_clong" in props["exits"] %}
exit_result_ok_clong:
        {{target.getAssignFromLongExpressionCode("result", "clong_result")}}
        return true;
{% endif %}

{% if left.isDualType() %}
    } else if (left_c_usable == false && right_c_usable) {
        PyObject *python_result = BINARY_OPERATION_{{op_code}}_OBJECT_{{left.getDualType("Python").getHelperCodeName()}}_{{right.getDualType("C").getHelperCodeName()}}({{left.getDualTypeAccessCode("Python", "operand1")}}, {{right.getDualTypeAccessCode("C", "operand2")}});

        if (unlikely(python_result == NULL)) {
            return false;
        }

        {{ target.getSetDualValueCode("Python", "result", "python_result") }}
        return true;
{% endif %}
{% if right.isDualType() %}
    } else if (left_c_usable && right_c_usable == false) {
{% if left.isCommutativeType() and right.isCommutativeType() and isCommutativeOperation(op_code) %}
        PyObject *python_result = BINARY_OPERATION_{{op_code}}_OBJECT_{{right.getDualType("Python").getHelperCodeName()}}_{{left.getDualType("C").getHelperCodeName()}}({{right.getDualTypeAccessCode("Python", "operand2")}}, {{left.getDualTypeAccessCode("C", "operand1")}});
{% else %}
        PyObject *python_result = BINARY_OPERATION_{{op_code}}_OBJECT_{{left.getDualType("C").getHelperCodeName()}}_{{right.getDualType("Python").getHelperCodeName()}}({{left.getDualTypeAccessCode("C", "operand1")}}, {{right.getDualTypeAccessCode("Python", "operand2")}});
{% endif %}

        if (unlikely(python_result == NULL)) {
            return false;
        }

        {{ target.getSetDualValueCode("Python", "result", "python_result") }}

        return true;
{% endif %}
    } else {
{% if left.isDualType() and right.isDualType() %}
        PyObject *python_result = BINARY_OPERATION_{{op_code}}_OBJECT_{{left.getDualType("Python").getHelperCodeName()}}_{{right.getDualType("Python").getHelperCodeName()}}({{left.getDualTypeAccessCode("Python", "operand1")}}, {{right.getDualTypeAccessCode("Python", "operand1")}});

        if (unlikely(python_result == NULL)) {
            return false;
        }

        {{ target.getSetDualValueCode("Python", "result", "python_result") }}

        return true;
{% else %}
        NUITKA_CANNOT_GET_HERE("cannot happen with types {{left.getHelperCodeName()}} {{right.getHelperCodeName()}}");
        return false;
{% endif %}
    }
}

{#     Part of "Nuitka", an optimizing Python compiler that is compatible and   #}
{#     integrates with CPython, but also works on its own.                      #}
{#                                                                              #}
{#     Licensed under the Apache License, Version 2.0 (the "License");          #}
{#     you may not use this file except in compliance with the License.         #}
{#     You may obtain a copy of the License at                                  #}
{#                                                                              #}
{#        http://www.apache.org/licenses/LICENSE-2.0                            #}
{#                                                                              #}
{#     Unless required by applicable law or agreed to in writing, software      #}
{#     distributed under the License is distributed on an "AS IS" BASIS,        #}
{#     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #}
{#     See the License for the specific language governing permissions and      #}
{#     limitations under the License.                                           #}
