Exemplo n.º 1
0
        private static void ClipDecimal(Expression expression, ConversionBlock block, IType expectedType)
        {
            var toFloat = Helpers.IsFloatType(expectedType, block.Emitter.Resolver);

            if (toFloat || (block.Emitter.IsJavaScriptOverflowMode && !InsideOverflowContext(block.Emitter, expression)))
            {
                block.Write(JS.Types.SYSTEM_DECIMAL + ".toFloat");
                block.Write("(");
                block.AfterOutput += ")";
            }
            else
            {
                block.Write(JS.Types.SYSTEM_DECIMAL + ".toInt(");
                block.AfterOutput = ", " + BridgeTypes.ToJsName(expectedType, block.Emitter) + ")";
            }
        }
Exemplo n.º 2
0
        private static void ClipDecimal(Expression expression, ConversionBlock block, IType expectedType)
        {
            var toFloat = Helpers.IsFloatType(expectedType, block.Emitter.Resolver);

            if (toFloat || (block.Emitter.IsJavaScriptOverflowMode && !InsideOverflowContext(block.Emitter, expression)))
            {
                block.Write("Bridge.Decimal.toFloat");
                if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression))
                {
                    block.Write("(");
                    block.AfterOutput += ")";
                }
            }
            else
            {
                block.Write("Bridge.Decimal.toInt(");
                block.AfterOutput = ", " + BridgeTypes.ToJsName(expectedType, block.Emitter) + ")";
            }
        }
Exemplo n.º 3
0
        private static void NarrowingNumericOrEnumerationConversion(ConversionBlock block, Expression expression, IType targetType, bool fromFloatingPoint, bool isChecked, bool isNullable, bool isExplicit = true)
        {
            if (block.Emitter.IsJavaScriptOverflowMode && !InsideOverflowContext(block.Emitter, expression))
            {
                return;
            }

            if (isChecked)
            {
                block.Write(JS.Types.BRIDGE_INT + ".check(");

                if (fromFloatingPoint)
                {
                    block.Write(JS.Types.BRIDGE_INT + ".trunc");
                    block.WriteOpenParentheses();
                }

                //expression.AcceptVisitor(block.Emitter);

                if (fromFloatingPoint)
                {
                    block.AfterOutput += ")";
                }

                block.AfterOutput += ", ";
                block.AfterOutput += BridgeTypes.ToJsName(targetType, block.Emitter);
                block.AfterOutput += ")";
            }
            else
            {
                if (isNullable || fromFloatingPoint)
                {
                    targetType = NullableType.IsNullable(targetType) ? NullableType.GetUnderlyingType(targetType) : targetType;
                    string action = null;
                    if (targetType.IsKnownType(KnownTypeCode.Char))
                    {
                        action = "clipu16";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.SByte))
                    {
                        action = "clip8";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.Byte))
                    {
                        action = "clipu8";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.Int16))
                    {
                        action = "clip16";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.UInt16))
                    {
                        action = "clipu16";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.Int32))
                    {
                        action = "clip32";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.UInt32))
                    {
                        action = "clipu32";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.Int64))
                    {
                        action = "clip64";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.UInt64))
                    {
                        action = "clipu64";
                    }
                    else
                    {
                        throw new ArgumentException("Can not narrow to " + targetType, "targetType");
                    }

                    block.Write(JS.Types.BRIDGE_INT + ".");
                    block.Write(action);
                    if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression))
                    {
                        block.Write("(");
                        block.AfterOutput += ")";
                    }
                }
                else
                {
                    var skipOuterWrap = (expression.Parent is VariableInitializer) ||
                                        (expression.Parent is AssignmentExpression) ||
                                        targetType.IsKnownType(KnownTypeCode.Int64) ||
                                        targetType.IsKnownType(KnownTypeCode.UInt64) ||
                                        targetType.IsKnownType(KnownTypeCode.Int16) ||
                                        targetType.IsKnownType(KnownTypeCode.SByte);

                    bool skipInnerWrap = false;

                    var  rr             = block.Emitter.Resolver.ResolveNode(expression is CastExpression ? ((CastExpression)expression).Expression : expression, block.Emitter);
                    var  memberTargetrr = rr as MemberResolveResult;
                    bool isField        = memberTargetrr != null && memberTargetrr.Member is IField &&
                                          (memberTargetrr.TargetResult is ThisResolveResult ||
                                           memberTargetrr.TargetResult is LocalResolveResult);

                    if (rr is ThisResolveResult || rr is LocalResolveResult || rr is ConstantResolveResult || isField)
                    {
                        skipInnerWrap = true;
                    }

                    if (!skipOuterWrap)
                    {
                        block.WriteOpenParentheses();
                    }

                    if (targetType.IsKnownType(KnownTypeCode.Char))
                    {
                        if (!skipInnerWrap)
                        {
                            block.WriteOpenParentheses();
                            block.AfterOutput += ")";
                        }
                        block.AfterOutput += " & 65535";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.SByte))
                    {
                        block.Write(JS.Types.BRIDGE_INT + ".sxb(");
                        if (!skipInnerWrap)
                        {
                            block.WriteOpenParentheses();
                            block.AfterOutput += ")";
                        }
                        block.AfterOutput += " & 255)";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.Byte))
                    {
                        if (!skipInnerWrap)
                        {
                            block.WriteOpenParentheses();
                            block.AfterOutput += ")";
                        }
                        block.AfterOutput += " & 255";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.Int16))
                    {
                        block.Write(JS.Types.BRIDGE_INT + ".sxs(");
                        if (!skipInnerWrap)
                        {
                            block.WriteOpenParentheses();
                            block.AfterOutput += ")";
                        }
                        block.AfterOutput += " & 65535)";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.UInt16))
                    {
                        if (!skipInnerWrap)
                        {
                            block.WriteOpenParentheses();
                            block.AfterOutput += ")";
                        }
                        block.AfterOutput += " & 65535";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.Int32))
                    {
                        if (!skipInnerWrap)
                        {
                            block.WriteOpenParentheses();
                            block.AfterOutput += ")";
                        }
                        block.AfterOutput += " | 0";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.UInt32))
                    {
                        if (!skipInnerWrap)
                        {
                            block.WriteOpenParentheses();
                            block.AfterOutput += ")";
                        }
                        block.AfterOutput += " >>> 0";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.Int64))
                    {
                        block.Write(JS.Types.BRIDGE_INT + ".clip64(");
                        block.AfterOutput += ")";
                    }
                    else if (targetType.IsKnownType(KnownTypeCode.UInt64))
                    {
                        block.Write(JS.Types.BRIDGE_INT + ".clipu64(");
                        block.AfterOutput += ")";
                    }
                    else
                    {
                        throw new ArgumentException("Can not narrow to " + targetType, "targetType");
                    }

                    if (!skipOuterWrap)
                    {
                        block.AfterOutput += ")";
                    }
                }
            }
        }
Exemplo n.º 4
0
        private static void CheckLong(ConversionBlock block, Expression expression, IType expectedType, IType fromType, bool isChecked)
        {
            if (!NeedsNarrowingNumericConversion(fromType, expectedType))
            {
                return;
            }

            if (isChecked)
            {
                expectedType = NullableType.IsNullable(expectedType) ? NullableType.GetUnderlyingType(expectedType) : expectedType;
                block.Write(JS.Types.System.Int64.CHECK);
                block.WriteOpenParentheses();

                block.AfterOutput += ", ";
                block.AfterOutput += BridgeTypes.ToJsName(expectedType, block.Emitter);
                block.AfterOutput += ")";
            }
            else
            {
                string action = null;
                expectedType = NullableType.IsNullable(expectedType) ? NullableType.GetUnderlyingType(expectedType) : expectedType;

                if (block.Emitter.IsJavaScriptOverflowMode && !InsideOverflowContext(block.Emitter, expression))
                {
                    action = "toNumber";
                }
                else if (expectedType.IsKnownType(KnownTypeCode.Char))
                {
                    action = "clipu16";
                }
                else if (expectedType.IsKnownType(KnownTypeCode.SByte))
                {
                    action = "clip8";
                }
                else if (expectedType.IsKnownType(KnownTypeCode.Byte))
                {
                    action = "clipu8";
                }
                else if (expectedType.IsKnownType(KnownTypeCode.Int16))
                {
                    action = "clip16";
                }
                else if (expectedType.IsKnownType(KnownTypeCode.UInt16))
                {
                    action = "clipu16";
                }
                else if (expectedType.IsKnownType(KnownTypeCode.Int32))
                {
                    action = "clip32";
                }
                else if (expectedType.IsKnownType(KnownTypeCode.UInt32))
                {
                    action = "clipu32";
                }
                else if (expectedType.IsKnownType(KnownTypeCode.Int64))
                {
                    action = "clip64";
                }
                else if (expectedType.IsKnownType(KnownTypeCode.UInt64))
                {
                    action = "clipu64";
                }
                else
                {
                    throw new ArgumentException("Can not narrow to " + expectedType, "expectedType");
                }

                block.Write(JS.Types.System.Int64.NAME + ".");
                block.Write(action);
                if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression))
                {
                    block.Write("(");
                    block.AfterOutput += ")";
                }
            }
        }
Exemplo n.º 5
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.º 6
0
        public static bool CheckConversion(ConversionBlock block, Expression expression)
        {
            Conversion conversion = null;
            try
            {
                var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter);
                conversion = block.Emitter.Resolver.Resolver.GetConversion(expression);
                var expectedType = block.Emitter.Resolver.Resolver.GetExpectedType(expression);

                var invocationExpression = expression.Parent as InvocationExpression;
                if (invocationExpression != null && invocationExpression.Arguments.Any(a => a == expression))
                {
                    var index = invocationExpression.Arguments.ToList().IndexOf(expression);
                    var methodResolveResult = block.Emitter.Resolver.ResolveNode(invocationExpression, block.Emitter) as MemberResolveResult;

                    var m = methodResolveResult.Member as IMethod;
                    var arg = m.Parameters[index < m.Parameters.Count ? index : (m.Parameters.Count - 1)];

                    if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return false;
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return true;
                    }
                }

                var namedArgExpression = expression.Parent as NamedArgumentExpression;
                if (namedArgExpression != null)
                {
                    var namedArgResolveResult = block.Emitter.Resolver.ResolveNode(namedArgExpression, block.Emitter) as NamedArgumentResolveResult;

                    if (Helpers.IsDecimalType(namedArgResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return false;
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(namedArgResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return true;
                    }
                }

                var namedExpression = expression.Parent as NamedExpression;
                if (namedExpression != null)
                {
                    var namedResolveResult = block.Emitter.Resolver.ResolveNode(namedExpression, block.Emitter);

                    if (Helpers.IsDecimalType(namedResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return false;
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(namedResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return true;
                    }
                }

                var binaryOpExpr = expression.Parent as BinaryOperatorExpression;
                if (binaryOpExpr != null)
                {
                    var idx = binaryOpExpr.Left == expression ? 0 : 1;
                    var binaryOpRr = block.Emitter.Resolver.ResolveNode(binaryOpExpr, block.Emitter) as OperatorResolveResult;

                    if (Helpers.IsDecimalType(binaryOpRr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return false;
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(binaryOpRr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return true;
                    }
                }

                var assignmentExpr = expression.Parent as AssignmentExpression;
                if (assignmentExpr != null)
                {
                    var assigmentRr = block.Emitter.Resolver.ResolveNode(assignmentExpr, block.Emitter) as OperatorResolveResult;

                    if (Helpers.IsDecimalType(assigmentRr.Operands[1].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return false;
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(assigmentRr.Operands[1].Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return true;
                    }
                }

                var arrayInit = expression.Parent as ArrayInitializerExpression;
                if (arrayInit != null)
                {
                    while (arrayInit.Parent is ArrayInitializerExpression)
                    {
                        arrayInit = (ArrayInitializerExpression)arrayInit.Parent;
                    }

                    IType elementType = null;
                    var arrayCreate = arrayInit.Parent as ArrayCreateExpression;
                    if (arrayCreate != null)
                    {
                        var rrArrayType = block.Emitter.Resolver.ResolveNode(arrayCreate, block.Emitter);
                        if (rrArrayType.Type is TypeWithElementType)
                        {
                            elementType = ((TypeWithElementType)rrArrayType.Type).ElementType;
                        }
                        else
                        {
                            elementType = rrArrayType.Type;
                        }
                    }
                    else
                    {
                        var rrElemenet = block.Emitter.Resolver.ResolveNode(arrayInit.Parent, block.Emitter);
                        var pt = rrElemenet.Type as ParameterizedType;
                        if (pt != null)
                        {
                            elementType = pt.TypeArguments.Count > 0 ? pt.TypeArguments.First() : null;
                        }
                        else
                        {
                            var arrayType = rrElemenet.Type as TypeWithElementType;
                            if (arrayType != null)
                            {
                                elementType = arrayType.ElementType;
                            }
                            else
                            {
                                elementType = rrElemenet.Type;
                            }
                        }
                    }

                    if (elementType != null && Helpers.IsDecimalType(elementType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return false;
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(elementType) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return true;
                    }
                }

                if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    var castExpr = expression.Parent as CastExpression;
                    ResolveResult castTypeRr = null;
                    if (castExpr != null)
                    {
                        castTypeRr = block.Emitter.Resolver.ResolveNode(castExpr.Type, block.Emitter);
                    }

                    if (castTypeRr == null || !Helpers.IsDecimalType(castTypeRr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return false;
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(expectedType) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return true;
                    }
                }

                if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver))
                {
                    return false;
                }

                if (conversion == null)
                {
                    return false;
                }

                if (conversion.IsIdentityConversion)
                {
                    return false;
                }

                var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression);
                if (isNumLifted && !conversion.IsUserDefined)
                {
                    return false;
                }
                bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock);
                if (isLifted)
                {
                    block.Write("Bridge.Nullable.lift(");
                }

                if (conversion.IsUserDefined)
                {
                    var method = conversion.Method;

                    string inline = block.Emitter.GetInline(method);

                    if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline))
                    {
                        // Still returns true if Nullable.lift( was written.
                        return isLifted;
                    }

                    if (!string.IsNullOrWhiteSpace(inline))
                    {
                        if (expression is InvocationExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is ObjectCreateExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is UnaryOperatorExpression)
                        {
                            var unaryExpression = (UnaryOperatorExpression)expression;
                            var resolveOperator = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit();
                        }
                        else if (expression is BinaryOperatorExpression)
                        {
                            var binaryExpression = (BinaryOperatorExpression)expression;
                            var resolveOperator = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr, method), inline).Emit();
                        }
                        else
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit();
                        }

                        block.DisableEmitConversionExpression = true;

                        // Still returns true if Nullable.lift( was written.
                        return isLifted;
                    }
                    else
                    {
                        if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition))
                        {
                            // Still returns true if Nullable.lift( was written.
                            return isLifted;
                        }

                        block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter));
                        block.WriteDot();

                        block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName());
                    }

                    if (isLifted)
                    {
                        block.WriteComma();
                    }
                    else
                    {
                        block.WriteOpenParentheses();
                    }

                    return true;
                }
                // Still returns true if Nullable.lift( was written.
                return isLifted;
            }
            catch
            {
            }

            return false;
        }
Exemplo n.º 7
0
        private static bool CheckTypeConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion, string typeName, IsType isType)
        {
            if (conversion.IsUserDefined)
            {
                var m = conversion.Method;
                if (isType(m.ReturnType, block.Emitter.Resolver))
                {
                    return(false);
                }
            }

            if (expression is CastExpression)
            {
                var nestedExpr = ((CastExpression)expression).Expression;
                var nested_rr  = block.Emitter.Resolver.ResolveNode(nestedExpr, block.Emitter);

                if (!(nested_rr is ConversionResolveResult))
                {
                    return(false);
                }
            }

            var invocationExpression = expression.Parent as InvocationExpression;

            if (invocationExpression != null && invocationExpression.Arguments.Any(a => a == expression))
            {
                var index = invocationExpression.Arguments.ToList().IndexOf(expression);
                var methodResolveResult = block.Emitter.Resolver.ResolveNode(invocationExpression, block.Emitter) as MemberResolveResult;

                if (methodResolveResult != null)
                {
                    var m   = methodResolveResult.Member as IMethod;
                    var arg = m.Parameters[index < m.Parameters.Count ? index : (m.Parameters.Count - 1)];

                    if (isType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !isType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write(typeName);
                        if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        if (expression is CastExpression &&
                            ((CastExpression)expression).Expression is ParenthesizedExpression)
                        {
                            return(false);
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }
            }

            var objectCreateExpression = expression.Parent as ObjectCreateExpression;

            if (objectCreateExpression != null && objectCreateExpression.Arguments.Any(a => a == expression))
            {
                var index = objectCreateExpression.Arguments.ToList().IndexOf(expression);
                var methodResolveResult = block.Emitter.Resolver.ResolveNode(objectCreateExpression, block.Emitter) as MemberResolveResult;

                if (methodResolveResult != null)
                {
                    var m   = methodResolveResult.Member as IMethod;
                    var arg = m.Parameters[index < m.Parameters.Count ? index : (m.Parameters.Count - 1)];

                    if (isType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !isType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write(typeName);
                        if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        if (expression is CastExpression &&
                            ((CastExpression)expression).Expression is ParenthesizedExpression)
                        {
                            return(false);
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }
            }

            var namedArgExpression = expression.Parent as NamedArgumentExpression;

            if (namedArgExpression != null)
            {
                var namedArgResolveResult = block.Emitter.Resolver.ResolveNode(namedArgExpression, block.Emitter) as NamedArgumentResolveResult;

                if (isType(namedArgResolveResult.Type, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

                    block.Write(typeName);
                    if (NullableType.IsNullable(namedArgResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    if (expression is CastExpression &&
                        ((CastExpression)expression).Expression is ParenthesizedExpression)
                    {
                        return(false);
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
            }

            var namedExpression = expression.Parent as NamedExpression;

            if (namedExpression != null)
            {
                var namedResolveResult = block.Emitter.Resolver.ResolveNode(namedExpression, block.Emitter);

                if (isType(namedResolveResult.Type, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

                    block.Write(typeName);
                    if (NullableType.IsNullable(namedResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    if (expression is CastExpression &&
                        ((CastExpression)expression).Expression is ParenthesizedExpression)
                    {
                        return(false);
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
            }

            var binaryOpExpr = expression.Parent as BinaryOperatorExpression;

            if (binaryOpExpr != null)
            {
                var idx        = binaryOpExpr.Left == expression ? 0 : 1;
                var binaryOpRr = block.Emitter.Resolver.ResolveNode(binaryOpExpr, block.Emitter) as OperatorResolveResult;

                if (binaryOpRr != null && isType(binaryOpRr.Operands[idx].Type, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver))
                {
                    var isNullable = NullableType.IsNullable(binaryOpRr.Operands[idx].Type);
                    if (expression.IsNull)
                    {
                        return(false);
                    }

                    block.Write(typeName);
                    if (isNullable && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    if (expression is CastExpression &&
                        ((CastExpression)expression).Expression is ParenthesizedExpression)
                    {
                        return(false);
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
            }

            var conditionalExpr = expression.Parent as ConditionalExpression;

            if (conditionalExpr != null && conditionalExpr.Condition != expression)
            {
                var idx           = conditionalExpr.TrueExpression == expression ? 0 : 1;
                var conditionalrr = block.Emitter.Resolver.ResolveNode(conditionalExpr, block.Emitter) as OperatorResolveResult;

                if (conditionalrr != null && isType(conditionalrr.Operands[idx].Type, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

                    block.Write(typeName);
                    if (NullableType.IsNullable(conditionalrr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    if (expression is CastExpression &&
                        ((CastExpression)expression).Expression is ParenthesizedExpression)
                    {
                        return(false);
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
            }

            var assignmentExpr = expression.Parent as AssignmentExpression;

            if (assignmentExpr != null)
            {
                var assigmentRr = block.Emitter.Resolver.ResolveNode(assignmentExpr, block.Emitter) as OperatorResolveResult;

                if (isType(assigmentRr.Operands[1].Type, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

                    block.Write(typeName);
                    if (NullableType.IsNullable(assigmentRr.Operands[1].Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    if (expression is CastExpression &&
                        ((CastExpression)expression).Expression is ParenthesizedExpression)
                    {
                        return(false);
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
            }

            var indexerExpr = expression.Parent as IndexerExpression;

            if (indexerExpr != null)
            {
                var index = indexerExpr.Arguments.ToList().IndexOf(expression);

                if (index >= 0)
                {
                    var invocationrr = block.Emitter.Resolver.ResolveNode(indexerExpr, block.Emitter) as InvocationResolveResult;

                    if (invocationrr != null && isType(invocationrr.Member.Parameters.ElementAt(index).Type, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write(typeName);
                        if (NullableType.IsNullable(invocationrr.Member.Parameters.ElementAt(index).Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        if (expression is CastExpression &&
                            ((CastExpression)expression).Expression is ParenthesizedExpression)
                        {
                            return(false);
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }
            }

            var arrayInit = expression.Parent as ArrayInitializerExpression;

            if (arrayInit != null)
            {
                while (arrayInit.Parent is ArrayInitializerExpression)
                {
                    arrayInit = (ArrayInitializerExpression)arrayInit.Parent;
                }

                IType elementType = null;
                var   arrayCreate = arrayInit.Parent as ArrayCreateExpression;
                if (arrayCreate != null)
                {
                    var rrArrayType = block.Emitter.Resolver.ResolveNode(arrayCreate, block.Emitter);
                    if (rrArrayType.Type is TypeWithElementType)
                    {
                        elementType = ((TypeWithElementType)rrArrayType.Type).ElementType;
                    }
                    else
                    {
                        elementType = rrArrayType.Type;
                    }
                }
                else
                {
                    var rrElemenet = block.Emitter.Resolver.ResolveNode(arrayInit.Parent, block.Emitter);
                    var pt         = rrElemenet.Type as ParameterizedType;
                    if (pt != null && pt.TypeArguments.Count > 0)
                    {
                        if (pt.TypeArguments.Count == 1)
                        {
                            elementType = pt.TypeArguments.First();
                        }
                        else
                        {
                            var index = 0;
                            arrayInit = expression.Parent as ArrayInitializerExpression;

                            for (int i = 0; i < arrayInit.Elements.Count; i++)
                            {
                                if (expression == arrayInit.Elements.ElementAt(i))
                                {
                                    index = i;
                                    break;
                                }
                            }

                            elementType = index < pt.TypeArguments.Count ? pt.TypeArguments.ElementAt(index) : pt.TypeArguments.ElementAt(0);
                        }
                    }
                    else
                    {
                        var arrayType = rrElemenet.Type as TypeWithElementType;
                        if (arrayType != null)
                        {
                            elementType = arrayType.ElementType;
                        }
                        else
                        {
                            elementType = rrElemenet.Type;
                        }
                    }
                }

                if (elementType != null && isType(elementType, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

                    block.Write(typeName);
                    if (NullableType.IsNullable(elementType) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    if (expression is CastExpression &&
                        ((CastExpression)expression).Expression is ParenthesizedExpression)
                    {
                        return(false);
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
                else if (Helpers.Is64Type(rr.Type, block.Emitter.Resolver) &&
                         Helpers.IsFloatType(elementType, block.Emitter.Resolver) &&
                         !Helpers.IsDecimalType(elementType, block.Emitter.Resolver) &&
                         isType(rr.Type, block.Emitter.Resolver))
                {
                    block.Write("Bridge.Long.toNumber");
                    if (expression is CastExpression &&
                        ((CastExpression)expression).Expression is ParenthesizedExpression)
                    {
                        return(false);
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
            }

            if (isType(expectedType, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver) && !(conversion.IsExplicit && conversion.IsNumericConversion))
            {
                var           castExpr   = expression.Parent as CastExpression;
                ResolveResult castTypeRr = null;
                if (castExpr != null)
                {
                    castTypeRr = block.Emitter.Resolver.ResolveNode(castExpr.Type, block.Emitter);
                }

                /*if (castTypeRr == null || !isType(castTypeRr.Type, block.Emitter.Resolver))*/
                if (castTypeRr == null || !conversion.IsExplicit)
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

                    block.Write(typeName);
                    if (NullableType.IsNullable(expectedType) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }

                    if (expression is CastExpression &&
                        ((CastExpression)expression).Expression is ParenthesizedExpression)
                    {
                        return(false);
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 8
0
        public static bool CheckConversion(ConversionBlock block, Expression expression)
        {
            Conversion conversion = null;

            try
            {
                var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter);
                conversion = block.Emitter.Resolver.Resolver.GetConversion(expression);
                var expectedType = block.Emitter.Resolver.Resolver.GetExpectedType(expression);

                var invocationExpression = expression.Parent as InvocationExpression;
                if (invocationExpression != null && invocationExpression.Arguments.Any(a => a == expression))
                {
                    var index = invocationExpression.Arguments.ToList().IndexOf(expression);
                    var methodResolveResult = block.Emitter.Resolver.ResolveNode(invocationExpression, block.Emitter) as MemberResolveResult;

                    if (methodResolveResult != null)
                    {
                        var m   = methodResolveResult.Member as IMethod;
                        var arg = m.Parameters[index < m.Parameters.Count ? index : (m.Parameters.Count - 1)];

                        if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                        {
                            if (expression.IsNull)
                            {
                                return(false);
                            }

                            block.Write("Bridge.Decimal");
                            if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression))
                            {
                                block.Write(".lift");
                            }
                            block.WriteOpenParentheses();
                            return(true);
                        }
                    }
                }

                var namedArgExpression = expression.Parent as NamedArgumentExpression;
                if (namedArgExpression != null)
                {
                    var namedArgResolveResult = block.Emitter.Resolver.ResolveNode(namedArgExpression, block.Emitter) as NamedArgumentResolveResult;

                    if (Helpers.IsDecimalType(namedArgResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(namedArgResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }

                var namedExpression = expression.Parent as NamedExpression;
                if (namedExpression != null)
                {
                    var namedResolveResult = block.Emitter.Resolver.ResolveNode(namedExpression, block.Emitter);

                    if (Helpers.IsDecimalType(namedResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(namedResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }

                var binaryOpExpr = expression.Parent as BinaryOperatorExpression;
                if (binaryOpExpr != null)
                {
                    var idx        = binaryOpExpr.Left == expression ? 0 : 1;
                    var binaryOpRr = block.Emitter.Resolver.ResolveNode(binaryOpExpr, block.Emitter) as OperatorResolveResult;

                    if (binaryOpRr != null && Helpers.IsDecimalType(binaryOpRr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(binaryOpRr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }

                var conditionalExpr = expression.Parent as ConditionalExpression;
                if (conditionalExpr != null && conditionalExpr.Condition != expression)
                {
                    var idx           = conditionalExpr.TrueExpression == expression ? 0 : 1;
                    var conditionalrr = block.Emitter.Resolver.ResolveNode(conditionalExpr, block.Emitter) as OperatorResolveResult;

                    if (conditionalrr != null && Helpers.IsDecimalType(conditionalrr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(conditionalrr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }

                var assignmentExpr = expression.Parent as AssignmentExpression;
                if (assignmentExpr != null)
                {
                    var assigmentRr = block.Emitter.Resolver.ResolveNode(assignmentExpr, block.Emitter) as OperatorResolveResult;

                    if (Helpers.IsDecimalType(assigmentRr.Operands[1].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(assigmentRr.Operands[1].Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }

                var arrayInit = expression.Parent as ArrayInitializerExpression;
                if (arrayInit != null)
                {
                    while (arrayInit.Parent is ArrayInitializerExpression)
                    {
                        arrayInit = (ArrayInitializerExpression)arrayInit.Parent;
                    }

                    IType elementType = null;
                    var   arrayCreate = arrayInit.Parent as ArrayCreateExpression;
                    if (arrayCreate != null)
                    {
                        var rrArrayType = block.Emitter.Resolver.ResolveNode(arrayCreate, block.Emitter);
                        if (rrArrayType.Type is TypeWithElementType)
                        {
                            elementType = ((TypeWithElementType)rrArrayType.Type).ElementType;
                        }
                        else
                        {
                            elementType = rrArrayType.Type;
                        }
                    }
                    else
                    {
                        var rrElemenet = block.Emitter.Resolver.ResolveNode(arrayInit.Parent, block.Emitter);
                        var pt         = rrElemenet.Type as ParameterizedType;
                        if (pt != null)
                        {
                            elementType = pt.TypeArguments.Count > 0 ? pt.TypeArguments.First() : null;
                        }
                        else
                        {
                            var arrayType = rrElemenet.Type as TypeWithElementType;
                            if (arrayType != null)
                            {
                                elementType = arrayType.ElementType;
                            }
                            else
                            {
                                elementType = rrElemenet.Type;
                            }
                        }
                    }

                    if (elementType != null && Helpers.IsDecimalType(elementType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(elementType) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }

                if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    var           castExpr   = expression.Parent as CastExpression;
                    ResolveResult castTypeRr = null;
                    if (castExpr != null)
                    {
                        castTypeRr = block.Emitter.Resolver.ResolveNode(castExpr.Type, block.Emitter);
                    }

                    if (castTypeRr == null || !Helpers.IsDecimalType(castTypeRr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(expectedType) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }

                if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver))
                {
                    return(false);
                }

                if (conversion == null)
                {
                    return(false);
                }

                if (conversion.IsIdentityConversion)
                {
                    return(false);
                }

                var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression);
                if (isNumLifted && !conversion.IsUserDefined)
                {
                    return(false);
                }
                bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock);
                if (isLifted)
                {
                    block.Write("Bridge.Nullable.lift(");
                }

                if (conversion.IsUserDefined)
                {
                    var method = conversion.Method;

                    string inline = block.Emitter.GetInline(method);

                    if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline))
                    {
                        // Still returns true if Nullable.lift( was written.
                        return(isLifted);
                    }

                    if (!string.IsNullOrWhiteSpace(inline))
                    {
                        if (expression is InvocationExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is ObjectCreateExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is UnaryOperatorExpression)
                        {
                            var unaryExpression       = (UnaryOperatorExpression)expression;
                            var resolveOperator       = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit();
                        }
                        else if (expression is BinaryOperatorExpression)
                        {
                            var binaryExpression      = (BinaryOperatorExpression)expression;
                            var resolveOperator       = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr, method), inline).Emit();
                        }
                        else
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit();
                        }

                        block.DisableEmitConversionExpression = true;

                        // Still returns true if Nullable.lift( was written.
                        return(isLifted);
                    }
                    else
                    {
                        if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition))
                        {
                            // Still returns true if Nullable.lift( was written.
                            return(isLifted);
                        }

                        block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter));
                        block.WriteDot();

                        block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName());
                    }

                    if (isLifted)
                    {
                        block.WriteComma();
                    }
                    else
                    {
                        block.WriteOpenParentheses();
                    }

                    return(true);
                }
                // Still returns true if Nullable.lift( was written.
                return(isLifted);
            }
            catch
            {
            }

            return(false);
        }
Exemplo n.º 9
0
        public static int CheckConversion(ConversionBlock block, Expression expression)
        {
            try
            {
                var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter);
                var conversion = block.Emitter.Resolver.Resolver.GetConversion(expression);
                var expectedType = block.Emitter.Resolver.Resolver.GetExpectedType(expression);

                var level = ConversionBlock.CheckDecimalConversion(block, expression, rr, expectedType, conversion) ? 1 : 0;

                if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined)
                {
                    return level;
                }

                if (conversion == null)
                {
                    return level;
                }

                if (conversion.IsIdentityConversion)
                {
                    return level;
                }

                var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression);
                if (isNumLifted && !conversion.IsUserDefined)
                {
                    return level;
                }
                bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock) && !Helpers.IsDecimalType(expectedType, block.Emitter.Resolver);
                if (isLifted)
                {
                    level++;
                    block.Write("Bridge.Nullable.lift(");
                }

                if (conversion.IsUserDefined)
                {
                    var method = conversion.Method;

                    string inline = block.Emitter.GetInline(method);

                    if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline))
                    {
                        // Still returns true if Nullable.lift( was written.
                        return level;
                    }

                    if (!string.IsNullOrWhiteSpace(inline))
                    {
                        if (expression is InvocationExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is ObjectCreateExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is UnaryOperatorExpression)
                        {
                            var unaryExpression = (UnaryOperatorExpression)expression;
                            var resolveOperator = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit();
                        }
                        else if (expression is BinaryOperatorExpression)
                        {
                            var binaryExpression = (BinaryOperatorExpression)expression;
                            var resolveOperator = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr, method), inline).Emit();
                        }
                        else
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit();
                        }

                        block.DisableEmitConversionExpression = true;

                        // Still returns true if Nullable.lift( was written.
                        return level;
                    }
                    else
                    {
                        if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition))
                        {
                            // Still returns true if Nullable.lift( was written.
                            return level;
                        }

                        block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter));
                        block.WriteDot();

                        block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName());
                    }

                    if (isLifted)
                    {
                        block.WriteComma();
                    }
                    else
                    {
                        block.WriteOpenParentheses();
                        level++;
                    }

                    var arg = method.Parameters[0];

                    if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver) && !expression.IsNull)
                    {
                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        level++;
                    }

                    return level;
                }
                // Still returns true if Nullable.lift( was written.
                return level;
            }
            catch
            {
            }

            return 0;
        }
Exemplo n.º 10
0
        public static int CheckConversion(ConversionBlock block, Expression expression)
        {
            try
            {
                var rr           = block.Emitter.Resolver.ResolveNode(expression, block.Emitter);
                var conversion   = block.Emitter.Resolver.Resolver.GetConversion(expression);
                var expectedType = block.Emitter.Resolver.Resolver.GetExpectedType(expression);
                int level        = 0;

                if (block.Emitter.IsAssignment)
                {
                    return(level);
                }

                /*if (expression is ParenthesizedExpression && expression.Parent is CastExpression)
                 * {
                 *  return level;
                 * }*/

                if (conversion.IsUserDefined && expression.Parent is CastExpression && ((CastExpression)expression.Parent).Expression == expression)
                {
                    var parentConversion = block.Emitter.Resolver.Resolver.GetConversion((CastExpression)expression.Parent);

                    if (!parentConversion.IsUserDefined || parentConversion.Method.Equals(conversion.Method))
                    {
                        return(level);
                    }
                }

                if (rr is ConstantResolveResult && expression is CastExpression && !conversion.IsUserDefined)
                {
                    return(level);
                }

                var convrr = rr as ConversionResolveResult;

                if (convrr != null && convrr.Input is ConstantResolveResult && !convrr.Conversion.IsUserDefined)
                {
                    return(level);
                }

                if (convrr != null && !conversion.IsUserDefined)
                {
                    conversion   = convrr.Conversion;
                    rr           = convrr.Input;
                    expectedType = convrr.Type;
                }

                if (!((expression.Parent is CastExpression) && !(expression is CastExpression)))
                {
                    CheckNumericConversion(block, expression, rr, expectedType, conversion);
                }

                if (!(conversion.IsExplicit && conversion.IsNumericConversion))
                {
                    level = ConversionBlock.CheckDecimalConversion(block, expression, rr, expectedType, conversion) ? (level + 1) : level;
                }

                if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined)
                {
                    return(level);
                }

                if (!(conversion.IsExplicit && conversion.IsNumericConversion))
                {
                    level = ConversionBlock.CheckLongConversion(block, expression, rr, expectedType, conversion)
                        ? (level + 1)
                        : level;
                }

                if (Helpers.Is64Type(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined)
                {
                    return(level);
                }


                if (conversion == null)
                {
                    return(level);
                }

                if (conversion.IsIdentityConversion)
                {
                    return(level);
                }

                var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression);
                if (isNumLifted && !conversion.IsUserDefined)
                {
                    return(level);
                }
                bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock) && !Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.Is64Type(expectedType, block.Emitter.Resolver) && !NullableType.IsNullable(expectedType);
                if (isLifted)
                {
                    level++;
                    block.Write("Bridge.Nullable.getValue(");
                }

                if (conversion.IsUserDefined)
                {
                    var method = conversion.Method;

                    string inline = block.Emitter.GetInline(method);

                    if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline))
                    {
                        // Still returns true if Nullable.lift( was written.
                        return(level);
                    }

                    if (!string.IsNullOrWhiteSpace(inline))
                    {
                        if (expression is InvocationExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is ObjectCreateExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (ObjectCreateExpression)expression), inline).Emit();
                        }
                        else if (expression is UnaryOperatorExpression)
                        {
                            var unaryExpression       = (UnaryOperatorExpression)expression;
                            var resolveOperator       = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit();
                        }
                        else if (expression is BinaryOperatorExpression)
                        {
                            var binaryExpression      = (BinaryOperatorExpression)expression;
                            var resolveOperator       = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr, method), inline).Emit();
                        }
                        else
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit();
                        }

                        block.DisableEmitConversionExpression = true;

                        // Still returns true if Nullable.lift( was written.
                        return(level);
                    }
                    else
                    {
                        if (method.DeclaringTypeDefinition != null && (block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition) || Helpers.IsIgnoreCast(method.DeclaringTypeDefinition, block.Emitter)))
                        {
                            // Still returns true if Nullable.lift( was written.
                            return(level);
                        }

                        block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter));
                        block.WriteDot();

                        block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName());
                    }

                    if (isLifted)
                    {
                        block.WriteComma();
                    }
                    else
                    {
                        block.WriteOpenParentheses();
                        level++;
                    }

                    var arg = method.Parameters[0];

                    if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver) && !expression.IsNull)
                    {
                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        if (expression is CastExpression &&
                            ((CastExpression)expression).Expression is ParenthesizedExpression)
                        {
                            return(level);
                        }
                        block.WriteOpenParentheses();
                        level++;
                    }

                    if (Helpers.Is64Type(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.Is64Type(rr.Type, block.Emitter.Resolver) && !expression.IsNull)
                    {
                        var isUint = Helpers.IsULongType(arg.Type, block.Emitter.Resolver, arg.IsParams);
                        block.Write("Bridge." + (isUint ? "ULong" : "Long"));
                        if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        if (expression is CastExpression &&
                            ((CastExpression)expression).Expression is ParenthesizedExpression)
                        {
                            return(level);
                        }
                        block.WriteOpenParentheses();
                        level++;
                    }

                    return(level);
                }
                // Still returns true if Nullable.lift( was written.
                return(level);
            }
            catch
            {
            }

            return(0);
        }
Exemplo n.º 11
0
        public static bool CheckConversion(ConversionBlock block, Expression expression)
        {
            Conversion conversion = null;
            try
            {
                var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter);
                conversion = block.Emitter.Resolver.Resolver.GetConversion(expression);

                if (conversion == null)
                {
                    return false;
                }

                if (conversion.IsIdentityConversion)
                {
                    return false;
                }

                var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression);
                if (isNumLifted && !conversion.IsUserDefined)
                {
                    return false;
                }

                if (conversion.IsLifted && !isNumLifted)
                {
                    block.Write("Bridge.Nullable.lift(");
                }

                if (conversion.IsUserDefined)
                {
                    var method = conversion.Method;

                    string inline = block.Emitter.GetInline(method);

                    if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline))
                    {
                        // Still returns true if Nullable.lift( was written.
                        return conversion.IsLifted;
                    }

                    if (!string.IsNullOrWhiteSpace(inline))
                    {
                        if (expression is InvocationExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is ObjectCreateExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is UnaryOperatorExpression)
                        {
                            var unaryExpression = (UnaryOperatorExpression)expression;
                            var resolveOperator = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr), inline).Emit();
                        }
                        else if (expression is BinaryOperatorExpression)
                        {
                            var binaryExpression = (BinaryOperatorExpression)expression;
                            var resolveOperator = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr), inline).Emit();
                        }
                        else
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit();
                        }

                        block.DisableEmitConversionExpression = true;

                        // Still returns true if Nullable.lift( was written.
                        return conversion.IsLifted;
                    }
                    else
                    {
                        if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition))
                        {
                            // Still returns true if Nullable.lift( was written.
                            return conversion.IsLifted;
                        }

                        block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter));
                        block.WriteDot();

                        block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName());
                    }

                    if (conversion.IsLifted)
                    {
                        block.WriteComma();
                    }
                    else
                    {
                        block.WriteOpenParentheses();
                    }

                    return true;
                }
                // Still returns true if Nullable.lift( was written.
                return conversion.IsLifted;
            }
            catch
            {
            }

            return false;
        }
Exemplo n.º 12
0
        private static int CheckUserDefinedConversion(ConversionBlock block, Expression expression, Conversion conversion, int level, ResolveResult rr, IType expectedType)
        {
            if (conversion.IsUserDefined && !ConversionBlock.expressionIgnoreUserDefine.Contains(expression))
            {
                var method = conversion.Method;

                string inline = block.Emitter.GetInline(method);

                if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline))
                {
                    // Still returns true if Nullable.lift( was written.
                    return(level);
                }

                if (!string.IsNullOrWhiteSpace(inline))
                {
                    ConversionBlock.expressionIgnoreUserDefine.Add(expression);

                    if (expression is InvocationExpression)
                    {
                        new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                    }
                    else if (expression is ObjectCreateExpression)
                    {
                        new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (ObjectCreateExpression)expression), inline).Emit();
                    }
                    else if (expression is UnaryOperatorExpression)
                    {
                        var unaryExpression       = (UnaryOperatorExpression)expression;
                        var resolveOperator       = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter);
                        OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                        new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit();
                    }
                    else
                    {
                        new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression, method), inline, method).Emit();
                    }

                    block.DisableEmitConversionExpression = true;
                    ConversionBlock.expressionIgnoreUserDefine.Remove(expression);

                    // Still returns true if Nullable.lift( was written.
                    return(level);
                }
                else
                {
                    if (method.DeclaringTypeDefinition != null && (block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition) || Helpers.IsIgnoreCast(method.DeclaringTypeDefinition, block.Emitter)))
                    {
                        // Still returns true if Nullable.lift( was written.
                        return(level);
                    }

                    block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter));
                    block.WriteDot();

                    block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName());
                }

                block.WriteOpenParentheses();
                block.AfterOutput += ")";

                var arg = method.Parameters[0];

                if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver) && !expression.IsNull)
                {
                    block.Write(JS.Types.SYSTEM_DECIMAL);
                    if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write("." + JS.Funcs.Math.LIFT);
                    }
                    if (expression is CastExpression &&
                        ((CastExpression)expression).Expression is ParenthesizedExpression)
                    {
                        return(level);
                    }
                    block.WriteOpenParentheses();
                    block.AfterOutput += ")";
                }

                if (Helpers.Is64Type(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.Is64Type(rr.Type, block.Emitter.Resolver) && !expression.IsNull)
                {
                    var isUint = Helpers.IsULongType(arg.Type, block.Emitter.Resolver, arg.IsParams);
                    block.Write(isUint ? JS.Types.SYSTEM_UInt64 : JS.Types.System.Int64.NAME);
                    if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write("." + JS.Funcs.Math.LIFT);
                    }
                    if (expression is CastExpression &&
                        ((CastExpression)expression).Expression is ParenthesizedExpression)
                    {
                        return(level);
                    }
                    block.WriteOpenParentheses();
                    block.AfterOutput += ")";
                }
            }

            return(level);
        }
Exemplo n.º 13
0
        private static int DoConversion(ConversionBlock block, Expression expression, Conversion conversion, IType expectedType,
                                        int level, ResolveResult rr, bool ignoreConversionResolveResult = false)
        {
            if (ConversionBlock.expressionIgnoreUserDefine.Contains(expression) && conversion.IsUserDefined)
            {
                expectedType = conversion.Method.Parameters.First().Type;
            }

            if (block.Emitter.IsAssignment)
            {
                return(level);
            }

            if (expression is ParenthesizedExpression && ((ParenthesizedExpression)expression).Expression is CastExpression)
            {
                return(level);
            }

            if (conversion.IsUserDefined && expression.Parent is CastExpression &&
                ((CastExpression)expression.Parent).Expression == expression)
            {
                var parentConversion = block.Emitter.Resolver.Resolver.GetConversion((CastExpression)expression.Parent);

                if (!parentConversion.IsUserDefined || parentConversion.Method.Equals(conversion.Method))
                {
                    return(level);
                }
            }

            if (rr is ConstantResolveResult && expression is CastExpression && !conversion.IsUserDefined)
            {
                return(level);
            }

            var convrr = rr as ConversionResolveResult;

            if (convrr != null && convrr.Input is ConstantResolveResult && !convrr.Conversion.IsUserDefined)
            {
                return(level);
            }

            string afterUserDefined = "";

            if (convrr != null && !conversion.IsUserDefined && !ignoreConversionResolveResult)
            {
                if (expectedType != convrr.Type)
                {
                    if (expression.Parent is CastExpression &&
                        ((CastExpression)expression.Parent).Expression == expression)
                    {
                        var parentExpectedType = block.Emitter.Resolver.Resolver.GetExpectedType((CastExpression)expression.Parent);
                        var parentrr           = block.Emitter.Resolver.ResolveNode(expression.Parent, block.Emitter) as ConversionResolveResult;

                        if (parentrr != null && parentrr.Type != expectedType || parentrr == null && expectedType != parentExpectedType)
                        {
                            level             = ConversionBlock.DoConversion(block, expression, conversion, expectedType, level, rr, true);
                            afterUserDefined  = block.AfterOutput;
                            block.AfterOutput = "";
                        }
                    }
                    else
                    {
                        level             = ConversionBlock.DoConversion(block, expression, conversion, expectedType, level, rr, true);
                        afterUserDefined  = block.AfterOutput;
                        block.AfterOutput = "";
                    }
                }

                conversion   = convrr.Conversion;
                rr           = convrr.Input;
                expectedType = convrr.Type;
            }

            var isNumLifted = conversion != null && conversion.IsImplicit && conversion.IsLifted &&
                              conversion.IsNumericConversion && !(expression is BinaryOperatorExpression);
            bool skipUserConversion = conversion == null || (!conversion.IsUserDefined &&
                                                             (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) ||
                                                              Helpers.Is64Type(expectedType, block.Emitter.Resolver) ||
                                                              conversion.IsIdentityConversion ||
                                                              isNumLifted));

            if (!skipUserConversion && conversion.IsUserDefined &&
                (expression is BinaryOperatorExpression || expression is UnaryOperatorExpression ||
                 expression.Parent is AssignmentExpression))
            {
                level = ConversionBlock.CheckUserDefinedConversion(block, expression, conversion, level, rr, expectedType);

                if (conversion.IsUserDefined && block.DisableEmitConversionExpression)
                {
                    return(level);
                }

                afterUserDefined  = block.AfterOutput + afterUserDefined;
                block.AfterOutput = "";
            }

            if (!(conversion.IsExplicit && conversion.IsNumericConversion))
            {
                if (ConversionBlock.CheckDecimalConversion(block, expression, rr, expectedType, conversion, ignoreConversionResolveResult))
                {
                    block.AfterOutput += ")";
                }
            }

            if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined)
            {
                var s = block.AfterOutput;
                block.AfterOutput = "";
                if (!((expression.Parent is CastExpression) && !(expression is CastExpression)))
                {
                    ConversionBlock.CheckNumericConversion(block, expression, rr, expectedType, conversion);
                }

                block.AfterOutput = block.AfterOutput + s + afterUserDefined;
                return(level);
            }

            if (!(conversion.IsExplicit && conversion.IsNumericConversion))
            {
                if (ConversionBlock.CheckLongConversion(block, expression, rr, expectedType, conversion, ignoreConversionResolveResult))
                {
                    block.AfterOutput += ")";
                }
            }

            if (Helpers.Is64Type(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined)
            {
                var s = block.AfterOutput;
                block.AfterOutput = "";
                if (!((expression.Parent is CastExpression) && !(expression is CastExpression)))
                {
                    ConversionBlock.CheckNumericConversion(block, expression, rr, expectedType, conversion);
                }

                block.AfterOutput = block.AfterOutput + s + afterUserDefined;
                return(level);
            }

            if (!((expression.Parent is CastExpression) && !(expression is CastExpression)))
            {
                ConversionBlock.CheckNumericConversion(block, expression, rr, expectedType, conversion);
            }

            if (conversion.IsIdentityConversion)
            {
                block.AfterOutput = block.AfterOutput + afterUserDefined;
                return(level);
            }

            if (isNumLifted && !conversion.IsUserDefined)
            {
                block.AfterOutput = block.AfterOutput + afterUserDefined;
                return(level);
            }
            bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock) &&
                            !Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) &&
                            !Helpers.Is64Type(expectedType, block.Emitter.Resolver) && !NullableType.IsNullable(expectedType);

            if (isLifted)
            {
                block.Write(JS.Types.SYSTEM_NULLABLE + ".getValue(");
                block.AfterOutput += ")";
            }

            if (conversion.IsUserDefined &&
                !(expression is BinaryOperatorExpression || expression is UnaryOperatorExpression ||
                  expression.Parent is AssignmentExpression))
            {
                level = ConversionBlock.CheckUserDefinedConversion(block, expression, conversion, level, rr, expectedType);
            }

            block.AfterOutput = block.AfterOutput + afterUserDefined;
            return(level);
        }
Exemplo n.º 14
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);
                }
            }
        }
Exemplo n.º 15
0
        private static bool CheckDecimalConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion)
        {
            if (conversion.IsUserDefined)
            {
                var m = conversion.Method;
                if (Helpers.IsDecimalType(m.ReturnType, block.Emitter.Resolver))
                {
                    return(false);
                }
            }

            var invocationExpression = expression.Parent as InvocationExpression;

            if (invocationExpression != null && invocationExpression.Arguments.Any(a => a == expression))
            {
                var index = invocationExpression.Arguments.ToList().IndexOf(expression);
                var methodResolveResult = block.Emitter.Resolver.ResolveNode(invocationExpression, block.Emitter) as MemberResolveResult;

                if (methodResolveResult != null)
                {
                    var m   = methodResolveResult.Member as IMethod;
                    var arg = m.Parameters[index < m.Parameters.Count ? index : (m.Parameters.Count - 1)];

                    if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }
            }

            var namedArgExpression = expression.Parent as NamedArgumentExpression;

            if (namedArgExpression != null)
            {
                var namedArgResolveResult = block.Emitter.Resolver.ResolveNode(namedArgExpression, block.Emitter) as NamedArgumentResolveResult;

                if (Helpers.IsDecimalType(namedArgResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

                    block.Write("Bridge.Decimal");
                    if (NullableType.IsNullable(namedArgResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
            }

            var namedExpression = expression.Parent as NamedExpression;

            if (namedExpression != null)
            {
                var namedResolveResult = block.Emitter.Resolver.ResolveNode(namedExpression, block.Emitter);

                if (Helpers.IsDecimalType(namedResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

                    block.Write("Bridge.Decimal");
                    if (NullableType.IsNullable(namedResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
            }

            var binaryOpExpr = expression.Parent as BinaryOperatorExpression;

            if (binaryOpExpr != null)
            {
                var idx        = binaryOpExpr.Left == expression ? 0 : 1;
                var binaryOpRr = block.Emitter.Resolver.ResolveNode(binaryOpExpr, block.Emitter) as OperatorResolveResult;

                if (binaryOpRr != null && Helpers.IsDecimalType(binaryOpRr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

                    block.Write("Bridge.Decimal");
                    if (NullableType.IsNullable(binaryOpRr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
            }

            var conditionalExpr = expression.Parent as ConditionalExpression;

            if (conditionalExpr != null && conditionalExpr.Condition != expression)
            {
                var idx           = conditionalExpr.TrueExpression == expression ? 0 : 1;
                var conditionalrr = block.Emitter.Resolver.ResolveNode(conditionalExpr, block.Emitter) as OperatorResolveResult;

                if (conditionalrr != null && Helpers.IsDecimalType(conditionalrr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

                    block.Write("Bridge.Decimal");
                    if (NullableType.IsNullable(conditionalrr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
            }

            var assignmentExpr = expression.Parent as AssignmentExpression;

            if (assignmentExpr != null)
            {
                var assigmentRr = block.Emitter.Resolver.ResolveNode(assignmentExpr, block.Emitter) as OperatorResolveResult;

                if (Helpers.IsDecimalType(assigmentRr.Operands[1].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

                    block.Write("Bridge.Decimal");
                    if (NullableType.IsNullable(assigmentRr.Operands[1].Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
            }

            var arrayInit = expression.Parent as ArrayInitializerExpression;

            if (arrayInit != null)
            {
                while (arrayInit.Parent is ArrayInitializerExpression)
                {
                    arrayInit = (ArrayInitializerExpression)arrayInit.Parent;
                }

                IType elementType = null;
                var   arrayCreate = arrayInit.Parent as ArrayCreateExpression;
                if (arrayCreate != null)
                {
                    var rrArrayType = block.Emitter.Resolver.ResolveNode(arrayCreate, block.Emitter);
                    if (rrArrayType.Type is TypeWithElementType)
                    {
                        elementType = ((TypeWithElementType)rrArrayType.Type).ElementType;
                    }
                    else
                    {
                        elementType = rrArrayType.Type;
                    }
                }
                else
                {
                    var rrElemenet = block.Emitter.Resolver.ResolveNode(arrayInit.Parent, block.Emitter);
                    var pt         = rrElemenet.Type as ParameterizedType;
                    if (pt != null)
                    {
                        elementType = pt.TypeArguments.Count > 0 ? pt.TypeArguments.First() : null;
                    }
                    else
                    {
                        var arrayType = rrElemenet.Type as TypeWithElementType;
                        if (arrayType != null)
                        {
                            elementType = arrayType.ElementType;
                        }
                        else
                        {
                            elementType = rrElemenet.Type;
                        }
                    }
                }

                if (elementType != null && Helpers.IsDecimalType(elementType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

                    block.Write("Bridge.Decimal");
                    if (NullableType.IsNullable(elementType) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
            }

            if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
            {
                var           castExpr   = expression.Parent as CastExpression;
                ResolveResult castTypeRr = null;
                if (castExpr != null)
                {
                    castTypeRr = block.Emitter.Resolver.ResolveNode(castExpr.Type, block.Emitter);
                }

                if (castTypeRr == null || !Helpers.IsDecimalType(castTypeRr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

                    block.Write("Bridge.Decimal");
                    if (NullableType.IsNullable(expectedType) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    block.WriteOpenParentheses();
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 16
0
        public static bool CheckConversion(ConversionBlock block, Expression expression)
        {
            Conversion conversion = null;

            try
            {
                var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter);
                conversion = block.Emitter.Resolver.Resolver.GetConversion(expression);

                if (conversion == null)
                {
                    return(false);
                }

                if (conversion.IsIdentityConversion)
                {
                    return(false);
                }

                if (conversion.IsLifted)
                {
                    block.Write("Bridge.Nullable.lift(");
                }

                if (conversion.IsUserDefined)
                {
                    var method = conversion.Method;

                    string inline = block.Emitter.GetInline(method);

                    if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline))
                    {
                        return(false);
                    }

                    if (!string.IsNullOrWhiteSpace(inline))
                    {
                        if (expression is InvocationExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is ObjectCreateExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is UnaryOperatorExpression)
                        {
                            var unaryExpression       = (UnaryOperatorExpression)expression;
                            var resolveOperator       = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr), inline).Emit();
                        }
                        else if (expression is BinaryOperatorExpression)
                        {
                            var binaryExpression      = (BinaryOperatorExpression)expression;
                            var resolveOperator       = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr), inline).Emit();
                        }
                        else
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit();
                        }

                        block.DisableEmitConversionExpression = true;

                        return(false);
                    }
                    else
                    {
                        if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition))
                        {
                            return(false);
                        }

                        block.Write(block.Emitter.ShortenTypeName(Helpers.GetScriptFullName(method.DeclaringType)));
                        block.WriteDot();

                        block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName());
                    }

                    if (conversion.IsLifted)
                    {
                        block.WriteComma();
                    }
                    else
                    {
                        block.WriteOpenParentheses();
                    }

                    return(true);
                }
                else if (conversion.IsNumericConversion)
                {
                }
            }
            catch
            {
            }

            return(false);
        }
Exemplo n.º 17
0
        public static int CheckConversion(ConversionBlock block, Expression expression)
        {
            try
            {
                var rr           = block.Emitter.Resolver.ResolveNode(expression, block.Emitter);
                var conversion   = block.Emitter.Resolver.Resolver.GetConversion(expression);
                var expectedType = block.Emitter.Resolver.Resolver.GetExpectedType(expression);

                var level = ConversionBlock.CheckDecimalConversion(block, expression, rr, expectedType, conversion) ? 1 : 0;

                if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined)
                {
                    return(level);
                }

                if (conversion == null)
                {
                    return(level);
                }

                if (conversion.IsIdentityConversion)
                {
                    return(level);
                }

                var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression);
                if (isNumLifted && !conversion.IsUserDefined)
                {
                    return(level);
                }
                bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock) && !Helpers.IsDecimalType(expectedType, block.Emitter.Resolver);
                if (isLifted)
                {
                    level++;
                    block.Write("Bridge.Nullable.lift(");
                }

                if (conversion.IsUserDefined)
                {
                    var method = conversion.Method;

                    string inline = block.Emitter.GetInline(method);

                    if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline))
                    {
                        // Still returns true if Nullable.lift( was written.
                        return(level);
                    }

                    if (!string.IsNullOrWhiteSpace(inline))
                    {
                        if (expression is InvocationExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is ObjectCreateExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is UnaryOperatorExpression)
                        {
                            var unaryExpression       = (UnaryOperatorExpression)expression;
                            var resolveOperator       = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit();
                        }
                        else if (expression is BinaryOperatorExpression)
                        {
                            var binaryExpression      = (BinaryOperatorExpression)expression;
                            var resolveOperator       = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr, method), inline).Emit();
                        }
                        else
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit();
                        }

                        block.DisableEmitConversionExpression = true;

                        // Still returns true if Nullable.lift( was written.
                        return(level);
                    }
                    else
                    {
                        if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition))
                        {
                            // Still returns true if Nullable.lift( was written.
                            return(level);
                        }

                        block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter));
                        block.WriteDot();

                        block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName());
                    }

                    if (isLifted)
                    {
                        block.WriteComma();
                    }
                    else
                    {
                        block.WriteOpenParentheses();
                        level++;
                    }

                    var arg = method.Parameters[0];

                    if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver) && !expression.IsNull)
                    {
                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        level++;
                    }

                    return(level);
                }
                // Still returns true if Nullable.lift( was written.
                return(level);
            }
            catch
            {
            }

            return(0);
        }
Exemplo n.º 18
0
        private static bool CheckDecimalConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion)
        {
            if (conversion.IsUserDefined)
            {
                var m = conversion.Method;
                if (Helpers.IsDecimalType(m.ReturnType, block.Emitter.Resolver))
                {
                    return false;
                }
            }

            var invocationExpression = expression.Parent as InvocationExpression;
            if (invocationExpression != null && invocationExpression.Arguments.Any(a => a == expression))
            {
                var index = invocationExpression.Arguments.ToList().IndexOf(expression);
                var methodResolveResult = block.Emitter.Resolver.ResolveNode(invocationExpression, block.Emitter) as MemberResolveResult;

                if (methodResolveResult != null)
                {
                    var m = methodResolveResult.Member as IMethod;
                    var arg = m.Parameters[index < m.Parameters.Count ? index : (m.Parameters.Count - 1)];

                    if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return false;
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return true;
                    }
                }
            }

            var namedArgExpression = expression.Parent as NamedArgumentExpression;
            if (namedArgExpression != null)
            {
                var namedArgResolveResult = block.Emitter.Resolver.ResolveNode(namedArgExpression, block.Emitter) as NamedArgumentResolveResult;

                if (Helpers.IsDecimalType(namedArgResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return false;
                    }

                    block.Write("Bridge.Decimal");
                    if (NullableType.IsNullable(namedArgResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    block.WriteOpenParentheses();
                    return true;
                }
            }

            var namedExpression = expression.Parent as NamedExpression;
            if (namedExpression != null)
            {
                var namedResolveResult = block.Emitter.Resolver.ResolveNode(namedExpression, block.Emitter);

                if (Helpers.IsDecimalType(namedResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return false;
                    }

                    block.Write("Bridge.Decimal");
                    if (NullableType.IsNullable(namedResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    block.WriteOpenParentheses();
                    return true;
                }
            }

            var binaryOpExpr = expression.Parent as BinaryOperatorExpression;
            if (binaryOpExpr != null)
            {
                var idx = binaryOpExpr.Left == expression ? 0 : 1;
                var binaryOpRr = block.Emitter.Resolver.ResolveNode(binaryOpExpr, block.Emitter) as OperatorResolveResult;

                if (binaryOpRr != null && Helpers.IsDecimalType(binaryOpRr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return false;
                    }

                    block.Write("Bridge.Decimal");
                    if (NullableType.IsNullable(binaryOpRr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    block.WriteOpenParentheses();
                    return true;
                }
            }

            var conditionalExpr = expression.Parent as ConditionalExpression;
            if (conditionalExpr != null && conditionalExpr.Condition != expression)
            {
                var idx = conditionalExpr.TrueExpression == expression ? 0 : 1;
                var conditionalrr = block.Emitter.Resolver.ResolveNode(conditionalExpr, block.Emitter) as OperatorResolveResult;

                if (conditionalrr != null && Helpers.IsDecimalType(conditionalrr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return false;
                    }

                    block.Write("Bridge.Decimal");
                    if (NullableType.IsNullable(conditionalrr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    block.WriteOpenParentheses();
                    return true;
                }
            }

            var assignmentExpr = expression.Parent as AssignmentExpression;
            if (assignmentExpr != null)
            {
                var assigmentRr = block.Emitter.Resolver.ResolveNode(assignmentExpr, block.Emitter) as OperatorResolveResult;

                if (Helpers.IsDecimalType(assigmentRr.Operands[1].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return false;
                    }

                    block.Write("Bridge.Decimal");
                    if (NullableType.IsNullable(assigmentRr.Operands[1].Type) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    block.WriteOpenParentheses();
                    return true;
                }
            }

            var arrayInit = expression.Parent as ArrayInitializerExpression;
            if (arrayInit != null)
            {
                while (arrayInit.Parent is ArrayInitializerExpression)
                {
                    arrayInit = (ArrayInitializerExpression)arrayInit.Parent;
                }

                IType elementType = null;
                var arrayCreate = arrayInit.Parent as ArrayCreateExpression;
                if (arrayCreate != null)
                {
                    var rrArrayType = block.Emitter.Resolver.ResolveNode(arrayCreate, block.Emitter);
                    if (rrArrayType.Type is TypeWithElementType)
                    {
                        elementType = ((TypeWithElementType)rrArrayType.Type).ElementType;
                    }
                    else
                    {
                        elementType = rrArrayType.Type;
                    }
                }
                else
                {
                    var rrElemenet = block.Emitter.Resolver.ResolveNode(arrayInit.Parent, block.Emitter);
                    var pt = rrElemenet.Type as ParameterizedType;
                    if (pt != null)
                    {
                        elementType = pt.TypeArguments.Count > 0 ? pt.TypeArguments.First() : null;
                    }
                    else
                    {
                        var arrayType = rrElemenet.Type as TypeWithElementType;
                        if (arrayType != null)
                        {
                            elementType = arrayType.ElementType;
                        }
                        else
                        {
                            elementType = rrElemenet.Type;
                        }
                    }
                }

                if (elementType != null && Helpers.IsDecimalType(elementType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return false;
                    }

                    block.Write("Bridge.Decimal");
                    if (NullableType.IsNullable(elementType) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    block.WriteOpenParentheses();
                    return true;
                }
            }

            if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
            {
                var castExpr = expression.Parent as CastExpression;
                ResolveResult castTypeRr = null;
                if (castExpr != null)
                {
                    castTypeRr = block.Emitter.Resolver.ResolveNode(castExpr.Type, block.Emitter);
                }

                if (castTypeRr == null || !Helpers.IsDecimalType(castTypeRr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return false;
                    }

                    block.Write("Bridge.Decimal");
                    if (NullableType.IsNullable(expectedType) && ConversionBlock.ShouldBeLifted(expression))
                    {
                        block.Write(".lift");
                    }
                    block.WriteOpenParentheses();
                    return true;
                }
            }

            return false;
        }