Exemplo n.º 1
0
        private static void CheckNumericConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion)
        {
            var fromType = rr.Type;
            var toType   = expectedType;

            if (fromType.Kind == TypeKind.Enum)
            {
                fromType = fromType.GetDefinition().EnumUnderlyingType;
            }

            if (toType.Kind == TypeKind.Enum)
            {
                toType = toType.GetDefinition().EnumUnderlyingType;
            }

            bool isArrayIndex = false;

            if (Helpers.Is64Type(toType, block.Emitter.Resolver) && expression.Parent is IndexerExpression &&
                ((IndexerExpression)expression.Parent).Arguments.Contains(expression))
            {
                var             memberResolveResult = rr as MemberResolveResult;
                var             isIgnore            = true;
                var             isAccessorsIndexer  = false;
                IProperty       member  = null;
                IndexerAccessor current = null;

                if (memberResolveResult == null)
                {
                    memberResolveResult = block.Emitter.Resolver.ResolveNode(expression.Parent, block.Emitter) as MemberResolveResult;
                }

                if (memberResolveResult != null)
                {
                    var resolvedMember = memberResolveResult.Member;
                    isIgnore           = block.Emitter.Validator.IsExternalType(resolvedMember.DeclaringTypeDefinition);
                    isAccessorsIndexer = block.Emitter.Validator.IsAccessorsIndexer(resolvedMember);

                    var property = resolvedMember as IProperty;
                    if (property != null)
                    {
                        member  = property;
                        current = IndexerBlock.GetIndexerAccessor(block.Emitter, member, block.Emitter.IsAssignment);
                    }
                }

                if (!(current != null && current.InlineAttr != null) && !(!(isIgnore || (current != null && current.IgnoreAccessor)) || isAccessorsIndexer))
                {
                    block.Write(JS.Types.System.Int64.TONUMBER);
                    block.Write("(");
                    isArrayIndex = true;
                }
            }

            if ((conversion.IsNumericConversion || conversion.IsEnumerationConversion) && conversion.IsExplicit)
            {
                if (!(expression.Parent is ArrayInitializerExpression) &&
                    Helpers.Is64Type(fromType, block.Emitter.Resolver) &&
                    Helpers.IsFloatType(toType, block.Emitter.Resolver) &&
                    !Helpers.IsDecimalType(toType, block.Emitter.Resolver))
                {
                    var be = expression.Parent as BinaryOperatorExpression;

                    if (be == null || be.Operator != BinaryOperatorType.Divide || be.Left != expression)
                    {
                        block.Write(JS.Types.System.Int64.TONUMBER);
                        if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression))
                        {
                            block.Write("(");
                            block.AfterOutput += ")";
                        }
                    }
                }
                else if (Helpers.IsDecimalType(toType, block.Emitter.Resolver) && !Helpers.IsDecimalType(fromType, block.Emitter.Resolver))
                {
                    block.Write(JS.Types.SYSTEM_DECIMAL + "(");
                    block.AfterOutput += ", null, " + BridgeTypes.ToJsName(fromType, block.Emitter) + ")";
                }
                else if (Helpers.IsDecimalType(fromType, block.Emitter.Resolver))
                {
                    ClipDecimal(expression, block, toType);
                }
                else if (Helpers.Is64Type(fromType, block.Emitter.Resolver))
                {
                    CheckLong(block, expression, toType, fromType, IsInCheckedContext(block.Emitter, expression));
                }
                else if (Helpers.IsFloatType(fromType, block.Emitter.Resolver) && Helpers.IsIntegerType(toType, block.Emitter.Resolver))
                {
                    FloatToInt(block, expression, fromType, toType, IsInCheckedContext(block.Emitter, expression));
                }
                else if (NeedsNarrowingNumericConversion(fromType, toType))
                {
                    if (IsInCheckedContext(block.Emitter, expression))
                    {
                        CheckInteger(block, expression, toType);
                    }
                    else
                    {
                        ClipInteger(block, expression, toType, true);
                    }
                }
            }
            else if (conversion.IsNumericConversion && conversion.IsImplicit && !(expression.Parent is ArrayInitializerExpression) &&
                     Helpers.Is64Type(fromType, block.Emitter.Resolver) &&
                     Helpers.IsFloatType(toType, block.Emitter.Resolver) &&
                     !Helpers.IsDecimalType(toType, block.Emitter.Resolver))
            {
                var be = expression.Parent as BinaryOperatorExpression;

                if (be == null || be.Operator != BinaryOperatorType.Divide || be.Left != expression)
                {
                    block.Write(JS.Types.System.Int64.TONUMBER);
                    if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression))
                    {
                        block.Write("(");
                        block.AfterOutput += ")";
                    }
                }
            }
            else if (((!Helpers.Is64Type(toType, block.Emitter.Resolver) && Helpers.IsIntegerType(toType, block.Emitter.Resolver)) ||
                      (rr is OperatorResolveResult && !Helpers.Is64Type(fromType, block.Emitter.Resolver) && Helpers.IsIntegerType(fromType, block.Emitter.Resolver))) &&
                     (expression is BinaryOperatorExpression || expression is UnaryOperatorExpression || expression.Parent is AssignmentExpression) &&
                     IsInCheckedContext(block.Emitter, expression))
            {
                var needCheck = false;

                var  be = expression as BinaryOperatorExpression;
                bool isBitwiseOperator = be != null && (be.Operator == BinaryOperatorType.ShiftLeft || be.Operator == BinaryOperatorType.ShiftRight || be.Operator == BinaryOperatorType.BitwiseAnd || be.Operator == BinaryOperatorType.BitwiseOr || be.Operator == BinaryOperatorType.ExclusiveOr);
                if ((Helpers.IsKnownType(KnownTypeCode.Int32, toType, block.Emitter.Resolver) && isBitwiseOperator) || (Helpers.IsKnownType(KnownTypeCode.UInt32, toType, block.Emitter.Resolver) && be != null && be.Operator == BinaryOperatorType.ShiftRight))
                {
                    // Don't need to check even in checked context and don't need to clip
                }
                else if (be != null && (be.Operator == BinaryOperatorType.Add ||
                                        be.Operator == BinaryOperatorType.Divide ||
                                        be.Operator == BinaryOperatorType.Multiply ||
                                        isBitwiseOperator ||
                                        be.Operator == BinaryOperatorType.Subtract))
                {
                    if (isBitwiseOperator)
                    {
                        ClipInteger(block, expression, toType, false);
                    }
                    else
                    {
                        needCheck = true;
                    }
                }
                else
                {
                    var ue = expression as UnaryOperatorExpression;

                    if (ue != null && (ue.Operator == UnaryOperatorType.Minus ||
                                       ue.Operator == UnaryOperatorType.Increment ||
                                       ue.Operator == UnaryOperatorType.Decrement ||
                                       ue.Operator == UnaryOperatorType.PostIncrement ||
                                       ue.Operator == UnaryOperatorType.PostDecrement))
                    {
                        needCheck = true;
                    }
                    else
                    {
                        var ae = expression.Parent as AssignmentExpression;
                        isBitwiseOperator = ae != null && (ae.Operator == AssignmentOperatorType.ShiftRight || ae.Operator == AssignmentOperatorType.ShiftLeft || ae.Operator == AssignmentOperatorType.BitwiseAnd || ae.Operator == AssignmentOperatorType.BitwiseOr || ae.Operator == AssignmentOperatorType.ExclusiveOr);
                        if ((isBitwiseOperator && Helpers.IsKnownType(KnownTypeCode.Int32, toType, block.Emitter.Resolver)) ||
                            (ae != null && ae.Operator == AssignmentOperatorType.ShiftRight && Helpers.IsKnownType(KnownTypeCode.UInt32, toType, block.Emitter.Resolver)))
                        {
                            // Don't need to check even in checked context and don't need to clip
                        }
                        else if (ae != null && (isBitwiseOperator || ae.Operator == AssignmentOperatorType.Add ||
                                                ae.Operator == AssignmentOperatorType.Divide ||
                                                ae.Operator == AssignmentOperatorType.Multiply ||
                                                ae.Operator == AssignmentOperatorType.Subtract))
                        {
                            if (isBitwiseOperator)
                            {
                                ClipInteger(block, expression, toType, false);
                            }
                            else
                            {
                                needCheck = true;
                            }
                        }
                    }
                }

                if (!Helpers.IsIntegerType(toType, block.Emitter.Resolver))
                {
                    if (rr is OperatorResolveResult)
                    {
                        toType = fromType;
                    }
                }

                if (needCheck)
                {
                    CheckInteger(block, expression, toType);
                }
            }
            else if (((!Helpers.Is64Type(toType, block.Emitter.Resolver) && Helpers.IsIntegerType(toType, block.Emitter.Resolver)) ||
                      (rr is OperatorResolveResult && !Helpers.Is64Type(fromType, block.Emitter.Resolver) && Helpers.IsIntegerType(fromType, block.Emitter.Resolver))) &&
                     (expression is BinaryOperatorExpression || expression is UnaryOperatorExpression || expression.Parent is AssignmentExpression) &&
                     IsInUncheckedContext(block.Emitter, expression))
            {
                if (ConversionBlock.IsLongConversion(block, expression, rr, toType, conversion) || rr is ConstantResolveResult)
                {
                    return;
                }

                if (!Helpers.IsIntegerType(toType, block.Emitter.Resolver))
                {
                    if (rr is OperatorResolveResult)
                    {
                        toType = fromType;
                    }
                }

                var needCheck = false;

                var  be = expression as BinaryOperatorExpression;
                bool isBitwiseOperator = be != null && (be.Operator == BinaryOperatorType.ShiftLeft || be.Operator == BinaryOperatorType.ShiftRight || be.Operator == BinaryOperatorType.BitwiseAnd || be.Operator == BinaryOperatorType.BitwiseOr || be.Operator == BinaryOperatorType.ExclusiveOr);

                if ((Helpers.IsKnownType(KnownTypeCode.Int32, toType, block.Emitter.Resolver) && isBitwiseOperator) || (Helpers.IsKnownType(KnownTypeCode.UInt32, toType, block.Emitter.Resolver) && be != null && be.Operator == BinaryOperatorType.ShiftRight))
                {
                    // Don't need to check even in checked context and don't need to clip
                }
                else if (be != null && !(be.Left is PrimitiveExpression && be.Right is PrimitiveExpression) && (be.Operator == BinaryOperatorType.Add ||
                                                                                                                be.Operator == BinaryOperatorType.Divide ||
                                                                                                                be.Operator == BinaryOperatorType.Multiply ||
                                                                                                                isBitwiseOperator ||
                                                                                                                be.Operator == BinaryOperatorType.Subtract))
                {
                    needCheck = true;
                }
                else
                {
                    var ue = expression as UnaryOperatorExpression;
                    if (ue != null && !(ue.Expression is PrimitiveExpression) && (ue.Operator == UnaryOperatorType.Minus ||
                                                                                  ue.Operator == UnaryOperatorType.Increment ||
                                                                                  ue.Operator == UnaryOperatorType.Decrement ||
                                                                                  ue.Operator == UnaryOperatorType.PostIncrement ||
                                                                                  ue.Operator == UnaryOperatorType.PostDecrement))
                    {
                        needCheck = true;
                    }
                    else
                    {
                        var ae = expression.Parent as AssignmentExpression;
                        isBitwiseOperator = ae != null && (ae.Operator == AssignmentOperatorType.ShiftRight || ae.Operator == AssignmentOperatorType.ShiftLeft || ae.Operator == AssignmentOperatorType.BitwiseAnd || ae.Operator == AssignmentOperatorType.BitwiseOr || ae.Operator == AssignmentOperatorType.ExclusiveOr);
                        if ((isBitwiseOperator && Helpers.IsKnownType(KnownTypeCode.Int32, toType, block.Emitter.Resolver)) ||
                            (ae != null && ae.Operator == AssignmentOperatorType.ShiftRight && Helpers.IsKnownType(KnownTypeCode.UInt32, toType, block.Emitter.Resolver)))
                        {
                            // Don't need to check even in checked context and don't need to clip
                        }
                        else if (ae != null && (isBitwiseOperator || ae.Operator == AssignmentOperatorType.Add ||
                                                ae.Operator == AssignmentOperatorType.Divide ||
                                                ae.Operator == AssignmentOperatorType.Multiply ||
                                                ae.Operator == AssignmentOperatorType.Subtract))
                        {
                            needCheck = true;
                        }
                    }
                }

                if (needCheck)
                {
                    ClipInteger(block, expression, toType, false);
                }
            }

            if (isArrayIndex)
            {
                block.AfterOutput += ")";
            }
        }
Exemplo n.º 2
0
        private static void CheckNumericConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion)
        {
            if (conversion.IsNumericConversion && conversion.IsExplicit)
            {
                var fromType = rr.Type;
                var toType   = expectedType;

                if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.IsDecimalType(fromType, block.Emitter.Resolver))
                {
                    block.Write("Bridge.Decimal(");
                    block.AfterOutput += ")";
                }
                else if (Helpers.IsDecimalType(fromType, block.Emitter.Resolver))
                {
                    ClipDecimal(expression, block, toType);
                }
                else if (Helpers.Is64Type(fromType, block.Emitter.Resolver))
                {
                    CheckLong(block, expression, toType, fromType, IsInCheckedContext(block.Emitter, expression));
                }
                else if (Helpers.IsFloatType(fromType, block.Emitter.Resolver) && Helpers.IsIntegerType(toType, block.Emitter.Resolver))
                {
                    FloatToInt(block, expression, fromType, toType, IsInCheckedContext(block.Emitter, expression));
                }
                else if (NeedsNarrowingNumericConversion(fromType, toType))
                {
                    if (IsInCheckedContext(block.Emitter, expression))
                    {
                        CheckInteger(block, expression, toType);
                    }
                    else
                    {
                        ClipInteger(block, expression, toType, true);
                    }
                }
            }
            else if (conversion.IsNumericConversion && conversion.IsImplicit && !(expression.Parent is ArrayInitializerExpression) &&
                     Helpers.Is64Type(rr.Type, block.Emitter.Resolver) &&
                     Helpers.IsFloatType(expectedType, block.Emitter.Resolver) &&
                     !Helpers.IsDecimalType(expectedType, block.Emitter.Resolver))
            {
                var be = expression.Parent as BinaryOperatorExpression;

                if (be == null || be.Operator != BinaryOperatorType.Divide || be.Left != expression)
                {
                    block.Write("Bridge.Long.toNumber");
                    if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression))
                    {
                        block.Write("(");
                        block.AfterOutput += ")";
                    }
                }
            }
            else if (((!Helpers.Is64Type(expectedType, block.Emitter.Resolver) && Helpers.IsIntegerType(expectedType, block.Emitter.Resolver)) ||
                      (rr is OperatorResolveResult && !Helpers.Is64Type(rr.Type, block.Emitter.Resolver) && Helpers.IsIntegerType(rr.Type, block.Emitter.Resolver))) &&
                     (expression is BinaryOperatorExpression || expression is UnaryOperatorExpression || expression.Parent is AssignmentExpression) &&
                     IsInCheckedContext(block.Emitter, expression))
            {
                var needCheck = false;

                var  be = expression as BinaryOperatorExpression;
                bool isBitwiseOperator = be != null && (be.Operator == BinaryOperatorType.ShiftLeft || be.Operator == BinaryOperatorType.ShiftRight || be.Operator == BinaryOperatorType.BitwiseAnd || be.Operator == BinaryOperatorType.BitwiseOr || be.Operator == BinaryOperatorType.ExclusiveOr);
                if ((Helpers.IsKnownType(KnownTypeCode.Int32, expectedType, block.Emitter.Resolver) && isBitwiseOperator) || (Helpers.IsKnownType(KnownTypeCode.UInt32, expectedType, block.Emitter.Resolver) && be != null && be.Operator == BinaryOperatorType.ShiftRight))
                {
                    // Don't need to check even in checked context and don't need to clip
                }
                else if (be != null && (be.Operator == BinaryOperatorType.Add ||
                                        be.Operator == BinaryOperatorType.Divide ||
                                        be.Operator == BinaryOperatorType.Multiply ||
                                        isBitwiseOperator ||
                                        be.Operator == BinaryOperatorType.Subtract))
                {
                    if (isBitwiseOperator)
                    {
                        ClipInteger(block, expression, expectedType, false);
                    }
                    else
                    {
                        needCheck = true;
                    }
                }
                else
                {
                    var ue = expression as UnaryOperatorExpression;

                    if (ue != null && (ue.Operator == UnaryOperatorType.Minus ||
                                       ue.Operator == UnaryOperatorType.Increment ||
                                       ue.Operator == UnaryOperatorType.Decrement ||
                                       ue.Operator == UnaryOperatorType.PostIncrement ||
                                       ue.Operator == UnaryOperatorType.PostDecrement))
                    {
                        needCheck = true;
                    }
                    else
                    {
                        var ae = expression.Parent as AssignmentExpression;
                        isBitwiseOperator = ae != null && (ae.Operator == AssignmentOperatorType.ShiftRight || ae.Operator == AssignmentOperatorType.ShiftLeft || ae.Operator == AssignmentOperatorType.BitwiseAnd || ae.Operator == AssignmentOperatorType.BitwiseOr || ae.Operator == AssignmentOperatorType.ExclusiveOr);
                        if ((isBitwiseOperator && Helpers.IsKnownType(KnownTypeCode.Int32, expectedType, block.Emitter.Resolver)) ||
                            (ae != null && ae.Operator == AssignmentOperatorType.ShiftRight && Helpers.IsKnownType(KnownTypeCode.UInt32, expectedType, block.Emitter.Resolver)))
                        {
                            // Don't need to check even in checked context and don't need to clip
                        }
                        else if (ae != null && (isBitwiseOperator || ae.Operator == AssignmentOperatorType.Add ||
                                                ae.Operator == AssignmentOperatorType.Divide ||
                                                ae.Operator == AssignmentOperatorType.Multiply ||
                                                ae.Operator == AssignmentOperatorType.Subtract))
                        {
                            if (isBitwiseOperator)
                            {
                                ClipInteger(block, expression, expectedType, false);
                            }
                            else
                            {
                                needCheck = true;
                            }
                        }
                    }
                }

                if (!Helpers.IsIntegerType(expectedType, block.Emitter.Resolver))
                {
                    if (rr is OperatorResolveResult)
                    {
                        expectedType = rr.Type;
                    }
                }

                if (needCheck)
                {
                    CheckInteger(block, expression, expectedType);
                }
            }
            else if (((!Helpers.Is64Type(expectedType, block.Emitter.Resolver) && Helpers.IsIntegerType(expectedType, block.Emitter.Resolver)) ||
                      (rr is OperatorResolveResult && !Helpers.Is64Type(rr.Type, block.Emitter.Resolver) && Helpers.IsIntegerType(rr.Type, block.Emitter.Resolver))) &&
                     (expression is BinaryOperatorExpression || expression is UnaryOperatorExpression || expression.Parent is AssignmentExpression) &&
                     IsInUncheckedContext(block.Emitter, expression))
            {
                if (ConversionBlock.IsLongConversion(block, expression, rr, expectedType, conversion) || rr is ConstantResolveResult)
                {
                    return;
                }

                if (!Helpers.IsIntegerType(expectedType, block.Emitter.Resolver))
                {
                    if (rr is OperatorResolveResult)
                    {
                        expectedType = rr.Type;
                    }
                }

                var needCheck = false;

                var  be = expression as BinaryOperatorExpression;
                bool isBitwiseOperator = be != null && (be.Operator == BinaryOperatorType.ShiftLeft || be.Operator == BinaryOperatorType.ShiftRight || be.Operator == BinaryOperatorType.BitwiseAnd || be.Operator == BinaryOperatorType.BitwiseOr || be.Operator == BinaryOperatorType.ExclusiveOr);

                if ((Helpers.IsKnownType(KnownTypeCode.Int32, expectedType, block.Emitter.Resolver) && isBitwiseOperator) || (Helpers.IsKnownType(KnownTypeCode.UInt32, expectedType, block.Emitter.Resolver) && be != null && be.Operator == BinaryOperatorType.ShiftRight))
                {
                    // Don't need to check even in checked context and don't need to clip
                }
                else if (be != null && !(be.Left is PrimitiveExpression && be.Right is PrimitiveExpression) && (be.Operator == BinaryOperatorType.Add ||
                                                                                                                be.Operator == BinaryOperatorType.Divide ||
                                                                                                                be.Operator == BinaryOperatorType.Multiply ||
                                                                                                                isBitwiseOperator ||
                                                                                                                be.Operator == BinaryOperatorType.Subtract))
                {
                    needCheck = true;
                }
                else
                {
                    var ue = expression as UnaryOperatorExpression;
                    if (ue != null && !(ue.Expression is PrimitiveExpression) && (ue.Operator == UnaryOperatorType.Minus ||
                                                                                  ue.Operator == UnaryOperatorType.Increment ||
                                                                                  ue.Operator == UnaryOperatorType.Decrement ||
                                                                                  ue.Operator == UnaryOperatorType.PostIncrement ||
                                                                                  ue.Operator == UnaryOperatorType.PostDecrement))
                    {
                        needCheck = true;
                    }
                    else
                    {
                        var ae = expression.Parent as AssignmentExpression;
                        isBitwiseOperator = ae != null && (ae.Operator == AssignmentOperatorType.ShiftRight || ae.Operator == AssignmentOperatorType.ShiftLeft || ae.Operator == AssignmentOperatorType.BitwiseAnd || ae.Operator == AssignmentOperatorType.BitwiseOr || ae.Operator == AssignmentOperatorType.ExclusiveOr);
                        if ((isBitwiseOperator && Helpers.IsKnownType(KnownTypeCode.Int32, expectedType, block.Emitter.Resolver)) ||
                            (ae != null && ae.Operator == AssignmentOperatorType.ShiftRight && Helpers.IsKnownType(KnownTypeCode.UInt32, expectedType, block.Emitter.Resolver)))
                        {
                            // Don't need to check even in checked context and don't need to clip
                        }
                        else if (ae != null && (isBitwiseOperator || ae.Operator == AssignmentOperatorType.Add ||
                                                ae.Operator == AssignmentOperatorType.Divide ||
                                                ae.Operator == AssignmentOperatorType.Multiply ||
                                                ae.Operator == AssignmentOperatorType.Subtract))
                        {
                            needCheck = true;
                        }
                    }
                }

                if (needCheck)
                {
                    ClipInteger(block, expression, expectedType, false);
                }
            }
        }