public BoundInterpolatedStringExpression(InterpolatedStringExpressionSyntax node, string builtStr, BoundExpression[] interpolatedExpressions, BindContext context)
            : base(node)
        {
            ValueType = context.GetTypeSymbol(SpecialType.System_String);

            BuiltStr = new BoundConstantExpression(new ConstantValue <string>(builtStr), ValueType, node);
            InterpolationExpressions = interpolatedExpressions;

            ObjectArr = context.GetTypeSymbol(SpecialType.System_Object).MakeArrayType(context);

            if (interpolatedExpressions.Length > 3)
            {
                StringFormatMethod = ValueType.GetMembers <ExternMethodSymbol>("Format", context).First(e =>
                                                                                                        e.Parameters[0].Type == ValueType && e.Parameters[1].Type == ObjectArr);
            }
            else
            {
                StringFormatMethod = ValueType.GetMembers <ExternMethodSymbol>("Format", context).First(e =>
                                                                                                        e.Parameters[0].Type == ValueType && e.Parameters.Length == interpolatedExpressions.Length + 1);
            }
        }
        public static BoundConstantExpression FoldConstantUnaryPrefixExpression(
            BindContext context,
            PrefixUnaryExpressionSyntax syntax,
            MethodSymbol unaryOperator,
            BoundExpression operand)
        {
            if (!operand.IsConstant)
            {
                return(null);
            }

            if (unaryOperator.IsOperator && unaryOperator.IsExtern)
            {
                object foldedValue;
                object operandValue = operand.ConstantValue.Value;

                switch (syntax.OperatorToken.Kind())
                {
                case SyntaxKind.MinusToken:
                    foldedValue = DynamicInvoke.UnaryNegate(operandValue);
                    break;

                case SyntaxKind.ExclamationToken:
                    foldedValue = DynamicInvoke.UnaryNot(operandValue);
                    break;

                case SyntaxKind.TildeToken:
                    foldedValue = DynamicInvoke.BitwiseNot(operandValue);
                    break;

                default:
                    return(null);
                }

                IConstantValue constantValue = (IConstantValue)Activator.CreateInstance(typeof(ConstantValue <>).MakeGenericType(foldedValue.GetType()), foldedValue);

                return(new BoundConstantExpression(constantValue, context.GetTypeSymbol(foldedValue.GetType()), syntax));
            }

            return(null);
        }
        public static BoundConstantExpression FoldConstantBinaryExpression(
            BindContext context,
            BinaryExpressionSyntax syntax,
            MethodSymbol binaryOperator,
            BoundExpression lhs, BoundExpression rhs)
        {
            // Value type + null comparison which will always be false for == and true for !=
            // This folding is needed for null comparisons in generics to work as expected
            if ((lhs.ValueType.IsValueType && rhs.IsConstant && rhs.ConstantValue.Value == null) ||
                (rhs.ValueType.IsValueType && lhs.IsConstant && lhs.ConstantValue.Value == null))
            {
                if (syntax.OperatorToken.Kind() == SyntaxKind.EqualsEqualsToken)
                {
                    return(new BoundConstantExpression(new ConstantValue <bool>(false),
                                                       context.GetTypeSymbol(typeof(bool)), syntax));
                }

                if (syntax.OperatorToken.Kind() == SyntaxKind.ExclamationEqualsToken)
                {
                    return(new BoundConstantExpression(new ConstantValue <bool>(true),
                                                       context.GetTypeSymbol(typeof(bool)), syntax));
                }
            }

            if (!lhs.IsConstant || !rhs.IsConstant)
            {
                return(null);
            }

            if (binaryOperator == null || (binaryOperator.IsOperator && binaryOperator.IsExtern))
            {
                object foldedValue;
                object lhsValue = lhs.ConstantValue.Value;
                object rhsValue = rhs.ConstantValue.Value;

                switch (syntax.OperatorToken.Kind())
                {
                case SyntaxKind.PlusToken:
                    foldedValue = DynamicInvoke.Add(lhsValue, rhsValue);
                    break;

                case SyntaxKind.MinusToken:
                    foldedValue = DynamicInvoke.Sub(lhsValue, rhsValue);
                    break;

                case SyntaxKind.AsteriskToken:
                    foldedValue = DynamicInvoke.Mul(lhsValue, rhsValue);
                    break;

                case SyntaxKind.SlashToken:
                    foldedValue = DynamicInvoke.Div(lhsValue, rhsValue);
                    break;

                case SyntaxKind.PercentToken:
                    foldedValue = DynamicInvoke.Mod(lhsValue, rhsValue);
                    break;

                case SyntaxKind.LessThanLessThanToken:
                    foldedValue = DynamicInvoke.LSh(lhsValue, rhsValue);
                    break;

                case SyntaxKind.GreaterThanGreaterThanToken:
                    foldedValue = DynamicInvoke.RSh(lhsValue, rhsValue);
                    break;

                case SyntaxKind.CaretToken:
                    foldedValue = DynamicInvoke.Xor(lhsValue, rhsValue);
                    break;

                case SyntaxKind.AmpersandToken:
                case SyntaxKind.AmpersandAmpersandToken:     // When we're dealing with constants short circuiting shouldn't matter
                    foldedValue = DynamicInvoke.BitwiseAnd(lhsValue, rhsValue);
                    break;

                case SyntaxKind.BarToken:
                case SyntaxKind.BarBarToken:
                    foldedValue = DynamicInvoke.BitwiseOr(lhsValue, rhsValue);
                    break;

                case SyntaxKind.GreaterThanToken:
                    foldedValue = DynamicInvoke.GreaterThan(lhsValue, rhsValue);
                    break;

                case SyntaxKind.GreaterThanEqualsToken:
                    foldedValue = DynamicInvoke.GreaterThanOrEquals(lhsValue, rhsValue);
                    break;

                case SyntaxKind.LessThanToken:
                    foldedValue = DynamicInvoke.LessThan(lhsValue, rhsValue);
                    break;

                case SyntaxKind.LessThanOrEqualExpression:
                    foldedValue = DynamicInvoke.LessThanOrEquals(lhsValue, rhsValue);
                    break;

                case SyntaxKind.EqualsEqualsToken:
                    foldedValue = DynamicInvoke.Equal(lhsValue, rhsValue);
                    break;

                case SyntaxKind.ExclamationEqualsToken:
                    foldedValue = DynamicInvoke.NotEqual(lhsValue, rhsValue);
                    break;

                default:
                    return(null);
                }

                IConstantValue constantValue = (IConstantValue)Activator.CreateInstance(typeof(ConstantValue <>).MakeGenericType(foldedValue.GetType()), foldedValue);

                return(new BoundConstantExpression(constantValue, context.GetTypeSymbol(foldedValue.GetType()), syntax));
            }

            return(null);
        }