示例#1
0
        internal static BoundExpression GiveTupleTypeToDefaultLiteralIfNeeded(BoundExpression expr, TypeSymbol targetType)
        {
            if (!expr.IsLiteralDefault() || targetType is null)
            {
                return(expr);
            }

            Debug.Assert(targetType.StrippedType().IsTupleType);
            return(new BoundDefaultExpression(expr.Syntax, targetType));
        }
示例#2
0
        private TupleBinaryOperatorInfo.Multiple BindTupleBinaryOperatorNestedInfo(BinaryExpressionSyntax node, BinaryOperatorKind kind,
                                                                                   BoundExpression left, BoundExpression right, DiagnosticBag diagnostics)
        {
            left  = GiveTupleTypeToDefaultLiteralIfNeeded(left, right.Type);
            right = GiveTupleTypeToDefaultLiteralIfNeeded(right, left.Type);

            if ((left.Type is null && left.IsLiteralDefault()) ||
                (right.Type is null && right.IsLiteralDefault()))
            {
                Error(diagnostics, ErrorCode.ERR_AmbigBinaryOps, node, node.OperatorToken.Text, left.Display, right.Display);
                return(TupleBinaryOperatorInfo.Multiple.ErrorInstance);
            }

            // Aside from default (which we fixed or ruled out above) and tuple literals,
            // we must have typed expressions at this point
            Debug.Assert((object)left.Type != null || left.Kind == BoundKind.TupleLiteral);
            Debug.Assert((object)right.Type != null || right.Kind == BoundKind.TupleLiteral);

            int leftCardinality  = GetTupleCardinality(left);
            int rightCardinality = GetTupleCardinality(right);

            if (leftCardinality != rightCardinality)
            {
                Error(diagnostics, ErrorCode.ERR_TupleSizesMismatchForBinOps, node, leftCardinality, rightCardinality);
                return(TupleBinaryOperatorInfo.Multiple.ErrorInstance);
            }

            (ImmutableArray <BoundExpression> leftParts, ImmutableArray <string> leftNames)   = GetTupleArgumentsOrPlaceholders(left);
            (ImmutableArray <BoundExpression> rightParts, ImmutableArray <string> rightNames) = GetTupleArgumentsOrPlaceholders(right);
            ReportNamesMismatchesIfAny(left, right, leftNames, rightNames, diagnostics);

            int length = leftParts.Length;

            Debug.Assert(length == rightParts.Length);

            var operatorsBuilder = ArrayBuilder <TupleBinaryOperatorInfo> .GetInstance(length);

            for (int i = 0; i < length; i++)
            {
                operatorsBuilder.Add(BindTupleBinaryOperatorInfo(node, kind, leftParts[i], rightParts[i], diagnostics));
            }

            var compilation = this.Compilation;
            var operators   = operatorsBuilder.ToImmutableAndFree();

            // typeless tuple literals are not nullable
            bool leftNullable  = left.Type?.IsNullableType() == true;
            bool rightNullable = right.Type?.IsNullableType() == true;
            bool isNullable    = leftNullable || rightNullable;

            TypeSymbol leftTupleType  = MakeConvertedType(operators.SelectAsArray(o => o.LeftConvertedTypeOpt), node.Left, leftParts, leftNames, isNullable, compilation, diagnostics);
            TypeSymbol rightTupleType = MakeConvertedType(operators.SelectAsArray(o => o.RightConvertedTypeOpt), node.Right, rightParts, rightNames, isNullable, compilation, diagnostics);

            return(new TupleBinaryOperatorInfo.Multiple(operators, leftTupleType, rightTupleType));
        }
示例#3
0
        private static bool IsTupleBinaryOperation(BoundExpression left, BoundExpression right)
        {
            bool leftDefault  = left.IsLiteralDefault();
            bool rightDefault = right.IsLiteralDefault();

            if (leftDefault && rightDefault)
            {
                return(false);
            }

            return((GetTupleCardinality(left) > 1 || leftDefault) && (GetTupleCardinality(right) > 1 || rightDefault));
        }
示例#4
0
 public static bool IsLiteralNullOrDefault(this BoundExpression node)
 {
     return(node.IsLiteralNull() || node.IsLiteralDefault());
 }