private bool TryGetValueFromBuiltinBinaryOp()

in src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Operators.cs [231:349]


        private bool TryGetValueFromBuiltinBinaryOp(PythonOperator op, BuiltinTypeId left, BuiltinTypeId right, bool is3x, out IMember member) {
            if (op.IsComparison()) {
                // All builtins compare to bool.
                member = Interpreter.GetBuiltinType(BuiltinTypeId.Bool);
                return true;
            }

            member = UnknownType;

            switch (op) {
                case PythonOperator.MatMultiply:
                    // No builtins implement this operator.
                    return true;

                case PythonOperator.BitwiseAnd:
                case PythonOperator.BitwiseOr:
                case PythonOperator.Xor:
                    switch (left) {
                        case BuiltinTypeId.Bool when right == BuiltinTypeId.Bool:
                            member = Interpreter.GetBuiltinType(BuiltinTypeId.Bool);
                            return true;

                        case BuiltinTypeId.Bool when right == BuiltinTypeId.Int:
                        case BuiltinTypeId.Int when right == BuiltinTypeId.Bool:
                        case BuiltinTypeId.Int when right == BuiltinTypeId.Int:
                            member = Interpreter.GetBuiltinType(BuiltinTypeId.Int);
                            return true;

                        case BuiltinTypeId.Long when right == BuiltinTypeId.Long:
                        case BuiltinTypeId.Long when right == BuiltinTypeId.Int:
                        case BuiltinTypeId.Long when right == BuiltinTypeId.Bool:
                        case BuiltinTypeId.Bool when right == BuiltinTypeId.Long:
                        case BuiltinTypeId.Int when right == BuiltinTypeId.Long:
                            member = Interpreter.GetBuiltinType(BuiltinTypeId.Long);
                            return true;
                    }

                    // All other combinations of these bitwise operaton on builtin types fail.
                    return true;
            }

            // At this point, @ & | ^ are all handled and do not need to be considered.

            if (CoalesceComplex(left, right)) {
                switch (op) {
                    case PythonOperator.Add:
                    case PythonOperator.Multiply:
                    case PythonOperator.Power:
                    case PythonOperator.Subtract:
                    case PythonOperator.Divide:
                    case PythonOperator.TrueDivide:
                    case PythonOperator.FloorDivide when !is3x:
                        member = Interpreter.GetBuiltinType(BuiltinTypeId.Complex);
                        return true;

                    case PythonOperator.FloorDivide when is3x:
                        // Complex numbers cannot be floordiv'd in Python 3.
                        return true;
                }
            }

            if (IsStringLike(left)) {
                member = HandleStringLike(op, left, right);
                return true;
            }

            if (IsStringLike(right)) {
                member = HandleStringLike(op, right, left);
                return true;
            }

            // All string-like cases have been handled.

            // If a complex value made it to here, then it wasn't coalesced or used in a string format; bail.
            if (left == BuiltinTypeId.Complex || right == BuiltinTypeId.Complex) {
                return true;
            }

            switch (op) {
                case PythonOperator.TrueDivide:
                    member = Interpreter.GetBuiltinType(BuiltinTypeId.Float);
                    return true;

                case PythonOperator.LeftShift:
                case PythonOperator.RightShift:
                    if (IsIntegerLike(left) && IsIntegerLike(right)) {
                        if (left == BuiltinTypeId.Long || right == BuiltinTypeId.Long) {
                            member = Interpreter.GetBuiltinType(BuiltinTypeId.Long);
                        } else {
                            member = Interpreter.GetBuiltinType(BuiltinTypeId.Int);
                        }
                        return true;
                    }

                    // If they aren't integer-like, then they can't be shifted.
                    return true;

                case PythonOperator.Add:
                case PythonOperator.Divide:
                case PythonOperator.FloorDivide:
                case PythonOperator.Mod:
                case PythonOperator.Power:
                case PythonOperator.Subtract:
                    if (IsIntegerLike(left) && IsIntegerLike(right)) {
                        if (left == BuiltinTypeId.Long || right == BuiltinTypeId.Long) {
                            member = Interpreter.GetBuiltinType(BuiltinTypeId.Long);
                        } else {
                            member = Interpreter.GetBuiltinType(BuiltinTypeId.Int);
                        }
                        return true;
                    } else if (left == BuiltinTypeId.Float || right == BuiltinTypeId.Float) {
                        member = Interpreter.GetBuiltinType(BuiltinTypeId.Float);
                        return true;
                    }
                    break;
            }

            return false;
        }