示例#1
0
 public override JSExpression Translate (ILBlockTranslator translator, JSExpression[] arguments) {
     return JSCastExpression.New(
         arguments[1],
         TargetType,
         translator.TypeSystem
     );
 }
示例#2
0
 public void VisitNode(JSCastExpression ce)
 {
     EmitCast(
         ce.Expression,
         ce.GetActualType(TypeSystem)
         );
 }
示例#3
0
        public void VisitNode(JSCastExpression cast)
        {
            var ct = GetCachedType(cast.NewType);

            if (ct != null)
            {
                cast.CachedTypeIndex = ct.Index;
            }

            VisitChildren(cast);
        }
示例#4
0
        private JSBinaryOperatorExpression MakeUnaryMutation(
            JSExpression expressionToMutate, JSBinaryOperator mutationOperator,
            TypeReference type
            )
        {
            var newValue = new JSBinaryOperatorExpression(
                mutationOperator, expressionToMutate, JSLiteral.New(1),
                TypeSystem.Int32
                );
            var assignment = new JSBinaryOperatorExpression(
                JSOperator.Assignment,
                expressionToMutate, JSCastExpression.New(
                    newValue, type, TypeSystem, true
                    ), type
                );

            return(assignment);
        }
示例#5
0
        public void VisitNode(JSCastExpression ce)
        {
            var currentType = ce.Expression.GetExpectedType(TypeSystem);
            var targetType = ce.NewType;
            JSExpression newExpression = null;

            if (ILBlockTranslator.IsEnum(currentType)) {
                var enumInfo = TypeInfo.GetExisting(currentType);

                if (targetType.MetadataType == MetadataType.Boolean) {
                    EnumMemberInfo enumMember;
                    if (enumInfo.ValueToEnumMember.TryGetValue(0, out enumMember)) {
                        newExpression = new JSBinaryOperatorExpression(
                            JSOperator.NotEqual, ce.Expression,
                            new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean
                        );
                    } else if (enumInfo.ValueToEnumMember.TryGetValue(1, out enumMember)) {
                        newExpression = new JSBinaryOperatorExpression(
                            JSOperator.Equal, ce.Expression,
                            new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean
                        );
                    } else {
                        newExpression = new JSUntranslatableExpression(String.Format(
                            "Could not cast enum of type '{0}' to boolean because it has no zero value or one value",
                            currentType.FullName
                        ));
                    }
                }
            }

            if (newExpression != null) {
                ParentNode.ReplaceChild(ce, newExpression);
                VisitReplacement(newExpression);
            } else {
                VisitChildren(ce);
            }
        }
示例#6
0
        public static JSExpression CastToEnumType(JSExpression value, TypeReference type, TypeSystem typeSystem)
        {
            if (IsNullableEnum(type))
            {
                // Handle casts like <int> -> <Enum?> by doing a two stage cast:
                // <int> -> <Enum> -> <Enum?>
                // Issue #154

                var git    = (GenericInstanceType)type;
                var casted = JSCastExpression.New(
                    value, git.GenericArguments[0], typeSystem, true
                    );
                var coerced = JSChangeTypeExpression.New(
                    casted, type, typeSystem
                    );
                return(coerced);
            }
            else
            {
                return(JSCastExpression.New(
                           value, type, typeSystem, true
                           ));
            }
        }
        public void VisitNode(JSCastExpression ce)
        {
            var currentType = ce.Expression.GetExpectedType(TypeSystem);
            var targetType = ce.NewType;

            JSExpression newExpression = null;

            if (targetType.MetadataType == MetadataType.Char) {
                newExpression = JSInvocationExpression.InvokeStatic(
                    JS.fromCharCode, new[] { ce.Expression }, true
                );
            } else if (
                (currentType.MetadataType == MetadataType.Char) &&
                ILBlockTranslator.IsIntegral(targetType)
            ) {
                newExpression = JSInvocationExpression.InvokeMethod(
                    JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true
                );
            } else if (
                ILBlockTranslator.IsEnum(currentType) &&
                ILBlockTranslator.IsIntegral(targetType)
            ) {
                newExpression = new JSDotExpression(
                    ce.Expression, new JSStringIdentifier("value", targetType)
                );
            } else {
                newExpression = JSIL.Cast(ce.Expression, targetType);
            }

            if (newExpression != null) {
                ParentNode.ReplaceChild(ce, newExpression);
                VisitReplacement(newExpression);
            } else {
                VisitChildren(ce);
            }
        }
        public void VisitNode(JSCastExpression ce)
        {
            var currentType = ce.Expression.GetActualType(TypeSystem);
            var targetType = ce.NewType;

            JSExpression newExpression = null;

            if (targetType.MetadataType == MetadataType.Char) {
                newExpression = JSInvocationExpression.InvokeStatic(
                    JS.fromCharCode, new[] { ce.Expression }, true
                );
            } else if (
                (currentType.MetadataType == MetadataType.Char) &&
                TypeUtil.IsIntegral(targetType)
            ) {
                newExpression = JSInvocationExpression.InvokeMethod(
                    JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true
                );
            } else if (
                IntroduceEnumCasts.IsEnumOrNullableEnum(currentType)
            ) {
                var enumInfo = TypeInfo.Get(currentType);

                if (targetType.MetadataType == MetadataType.Boolean) {
                    EnumMemberInfo enumMember;
                    if (enumInfo.ValueToEnumMember.TryGetValue(0, out enumMember)) {
                        newExpression = new JSBinaryOperatorExpression(
                            JSOperator.NotEqual, ce.Expression,
                            new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean
                        );
                    } else if (enumInfo.ValueToEnumMember.TryGetValue(1, out enumMember)) {
                        newExpression = new JSBinaryOperatorExpression(
                            JSOperator.Equal, ce.Expression,
                            new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean
                        );
                    } else {
                        newExpression = new JSUntranslatableExpression(String.Format(
                            "Could not cast enum of type '{0}' to boolean because it has no zero value or one value",
                            currentType.FullName
                        ));
                    }
                } else if (TypeUtil.IsNumeric(targetType)) {
                    newExpression = JSInvocationExpression.InvokeStatic(
                        JS.Number(targetType), new[] { ce.Expression }, true
                    );
                } else if (targetType.FullName == "System.Enum") {
                    newExpression = ce.Expression;
                } else {
                    // Debugger.Break();
                }
            } else if (
                targetType.MetadataType == MetadataType.Boolean
            ) {
                newExpression = new JSBinaryOperatorExpression(
                    JSBinaryOperator.NotEqual,
                    ce.Expression, new JSDefaultValueLiteral(currentType),
                    TypeSystem.Boolean
                );
            } else if (
                TypeUtil.IsNumeric(targetType) &&
                TypeUtil.IsNumeric(currentType)
            ) {
                if (
                    TypeUtil.IsIntegral(currentType) ||
                    !TypeUtil.IsIntegral(targetType)
                )
                    newExpression = ce.Expression;
                else
                    newExpression = JSInvocationExpression.InvokeStatic(JS.floor, new[] { ce.Expression }, true);
            } else {
                // newExpression = JSIL.Cast(ce.Expression, targetType);
            }

            if (newExpression != null) {
                ParentNode.ReplaceChild(ce, newExpression);
                VisitReplacement(newExpression);
            } else {
                // Debugger.Break();
                VisitChildren(ce);
            }
        }
示例#9
0
        public void VisitNode (JSCastExpression ce) {
            var currentType = ce.Expression.GetActualType(TypeSystem);
            var targetType = ce.NewType;

            JSExpression newExpression = null;
            var innerCast = ce.Expression as JSCastExpression;

            if (targetType.FullName == "System.ValueType") {
                var replacement = ce.Expression;
                ParentNode.ReplaceChild(ce, replacement);
                VisitReplacement(replacement);
                return;
            } else if (
                TypeUtil.IsIntegralOrEnum(currentType) &&
                (targetType.MetadataType == MetadataType.Char)
            ) {
                newExpression = JSInvocationExpression.InvokeStatic(
                    JS.fromCharCode, new[] { ce.Expression }, true
                );
            } else if (
                (currentType.MetadataType == MetadataType.Char) &&
                TypeUtil.IsIntegral(targetType)
            ) {
                newExpression = JSInvocationExpression.InvokeMethod(
                    JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true
                );
            } else if (
                IntroduceEnumCasts.IsEnumOrNullableEnum(currentType)
            ) {
                TypeInfo enumInfo;
                var isNullable = TypeUtil.IsNullable(currentType);

                if (isNullable) {
                    int temp;
                    var git = (GenericInstanceType)TypeUtil.FullyDereferenceType(currentType, out temp);
                    enumInfo = TypeInfo.Get(git.GenericArguments[0]);
                } else {
                    enumInfo = TypeInfo.Get(currentType);
                }

                if (enumInfo == null)
                    throw new InvalidOperationException("Unable to extract enum type from typereference " + currentType);

                if (targetType.MetadataType == MetadataType.Boolean) {
                    newExpression = new JSBinaryOperatorExpression(
                        JSOperator.NotEqual,
                        JSCastExpression.New(ce.Expression, TypeSystem.Int32, TypeSystem, true, true),
                        new JSIntegerLiteral(0, typeof(Int32)),
                        TypeSystem.Boolean
                    );
                } else if (TypeUtil.IsNumeric(targetType)) {
                    if (isNullable) {
                        newExpression = new JSNullableCastExpression(ce.Expression, new JSType(targetType));
                    } else if (
                        ce.Expression is JSCastExpression &&
                        (((JSCastExpression)ce.Expression).Expression.GetActualType(TypeSystem).MetadataType == MetadataType.Int64 ||
                        ((JSCastExpression)ce.Expression).Expression.GetActualType(TypeSystem).MetadataType == MetadataType.UInt64)
                    ) {
                        newExpression = ce.Expression;
                    } else {
                        newExpression = JSInvocationExpression.InvokeMethod(
                            JS.valueOf(targetType), ce.Expression, null, true
                        );
                    }
                } else if (targetType.FullName == "System.Enum") {
                    newExpression = ce.Expression;
                } else {
                    // Debugger.Break();
                }
            } else if (
                (targetType.MetadataType == MetadataType.Boolean) &&
                (ce.Expression is JSAsExpression) && 
                ((JSAsExpression)ce.Expression).GetActualType(TypeSystem) is GenericParameter
            ) {
                // C# expressions such as (t is T) (where T is a generic parameter). See issue #150. 
                // Tested with AsWithGenericParameter.cs
                newExpression = new JSBinaryOperatorExpression(
                    JSOperator.NotEqual,
                    ce.Expression, new JSNullLiteral(currentType),
                    TypeSystem.Boolean
                );  
            }
            else if (
                (targetType.MetadataType == MetadataType.Boolean) &&
                // A cast from Object to Boolean can occur in two forms:
                // An implied conversion, where an object expression is treated as a boolean (logicnot operation, etc).
                //  In this case, we want to do 'obj != null' to make it a boolean.
                // An explicit conversion, where an object expression is unboxed to boolean.
                //  In this case we want to leave it as-is.
                (ce.IsCoercion || (currentType.FullName != "System.Object"))
            ) {
                newExpression = new JSBinaryOperatorExpression(
                    JSOperator.NotEqual,
                    ce.Expression, new JSDefaultValueLiteral(currentType),
                    TypeSystem.Boolean
                );
            } else if (
                TypeUtil.IsNumeric(targetType) &&
                TypeUtil.IsNumeric(currentType) &&
                !TypeUtil.TypesAreEqual(targetType, currentType, true)
            ) {
                TypeReference innerType = null;
                if (innerCast != null)
                    innerType = innerCast.Expression.GetActualType(TypeSystem);

                if (
                    TypeUtil.TypesAreAssignable(TypeInfo, targetType, innerType) &&
                    (
                        (TypeUtil.IsFloatingPoint(targetType) == TypeUtil.IsFloatingPoint(currentType)) &&
                        (TypeUtil.IsFloatingPoint(targetType) == TypeUtil.IsFloatingPoint(innerType))
                    ) &&
                    (TypeUtil.IsSigned(targetType) == TypeUtil.IsSigned(innerType)) &&
                    (TypeUtil.SizeOfType(targetType) <= TypeUtil.SizeOfType(currentType)) &&
                    (TypeUtil.SizeOfType(targetType) >= TypeUtil.SizeOfType(innerType))
                ) {
                    // HACK: Turn pointless conversions like '(int32)(int64)(1 + 2)' into '(1 + 2)'
                    newExpression = innerCast.Expression;

                } else if (currentType.MetadataType == MetadataType.Int64) {
                    if (!EmulateInt64) {
                        newExpression = ce;
                    } else if (targetType.MetadataType == MetadataType.UInt64) {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToUInt64", TypeSystem.UInt64, new TypeReference[] { }, MethodTypeFactory),
                                ce.Expression);
                    } else {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToNumber", targetType, new TypeReference[] { TypeSystem.Double, TypeSystem.Boolean }, MethodTypeFactory),
                                ce.Expression,
                                GetInt64ConversionArgs(targetType));
                    }

                } else if (currentType.MetadataType == MetadataType.UInt64) { 
                    if (!EmulateInt64) {
                        newExpression = ce;
                    } else if (targetType.MetadataType == MetadataType.Int64) { 
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToInt64", TypeSystem.Int64, new TypeReference[] { }, MethodTypeFactory),
                                ce.Expression);
                    } else {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToNumber", targetType, new TypeReference[] { TypeSystem.Double, TypeSystem.Boolean }, MethodTypeFactory),
                                ce.Expression,
                                GetInt64ConversionArgs(targetType));
                    }

                } else if (targetType.MetadataType == MetadataType.Int64) {
                    if (!EmulateInt64) {
                        newExpression = ce;
                    } else {
                        newExpression = JSInvocationExpression.InvokeStatic(
                            new JSType(TypeSystem.Int64),
                            new JSFakeMethod("FromNumber", TypeSystem.Int64, new[] { currentType }, MethodTypeFactory),
                            new[] { ce.Expression }, true
                        );
                    }

                } else if (targetType.MetadataType == MetadataType.UInt64) {
                    if (!EmulateInt64) {
                        newExpression = ce;
                    } else {
                        newExpression = JSInvocationExpression.InvokeStatic(
                            new JSType(TypeSystem.UInt64),
                            new JSFakeMethod("FromNumber", TypeSystem.UInt64, new[] { currentType }, MethodTypeFactory),
                            new[] { ce.Expression }, true
                        );
                    }

                } else if (TypeUtil.IsIntegral(currentType)) {
                    if (!TypeUtil.IsIntegral(targetType)) {
                        // Integer -> float conversion
                        newExpression = new JSIntegerToFloatExpression(ce.Expression, targetType);
                    } else if (TypeUtil.SizeOfType(currentType) < TypeUtil.SizeOfType(targetType)) {
                        // Widening integer -> integer conversion
                        newExpression = ce.Expression;
                    } else {
                        newExpression = null;
                    }
                } else if (TypeUtil.IsIntegral(targetType)) {
                    newExpression = new JSTruncateExpression(ce.Expression);
                } else if (TypeUtil.SizeOfType(targetType) < TypeUtil.SizeOfType(currentType)) {
                    // Narrowing double -> float conversion
                    newExpression = new JSDoubleToFloatExpression(ce.Expression);
                } else {
                    // Widening float -> double conversion
                    newExpression = new JSFloatToDoubleExpression(ce.Expression);
                }
            } else {
                // newExpression = JSIL.Cast(ce.Expression, targetType);
            }

            if ((newExpression != null) && (newExpression != ce)) {
                ParentNode.ReplaceChild(ce, newExpression);
                VisitReplacement(newExpression);
            } else {
                // Debugger.Break();
                VisitChildren(ce);
            }
        }
示例#10
0
        public void VisitNode(JSCastExpression ce)
        {
            var currentType = ce.Expression.GetActualType(TypeSystem);
            var targetType  = ce.NewType;

            JSExpression newExpression = null;
            var          innerCast     = ce.Expression as JSCastExpression;

            if (targetType.FullName == "System.ValueType")
            {
                var replacement = ce.Expression;
                ParentNode.ReplaceChild(ce, replacement);
                VisitReplacement(replacement);
                return;
            }
            else if (
                TypeUtil.IsIntegralOrEnum(currentType) &&
                (targetType.MetadataType == MetadataType.Char)
                )
            {
                newExpression = JSInvocationExpression.InvokeStatic(
                    JS.fromCharCode, new[] { ce.Expression }, true
                    );
            }
            else if (
                (currentType.MetadataType == MetadataType.Char) &&
                TypeUtil.IsIntegral(targetType)
                )
            {
                newExpression = JSInvocationExpression.InvokeMethod(
                    JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true
                    );
            }
            else if (
                IntroduceEnumCasts.IsEnumOrNullableEnum(currentType)
                )
            {
                TypeInfo enumInfo;
                var      isNullable = TypeUtil.IsNullable(currentType);

                if (isNullable)
                {
                    int temp;
                    var git = (GenericInstanceType)TypeUtil.FullyDereferenceType(currentType, out temp);
                    enumInfo = TypeInfo.Get(git.GenericArguments[0]);
                }
                else
                {
                    enumInfo = TypeInfo.Get(currentType);
                }

                if (enumInfo == null)
                {
                    throw new InvalidOperationException("Unable to extract enum type from typereference " + currentType);
                }

                if (targetType.MetadataType == MetadataType.Boolean)
                {
                    newExpression = new JSBinaryOperatorExpression(
                        JSOperator.NotEqual,
                        JSCastExpression.New(ce.Expression, TypeSystem.Int32, TypeSystem, true, true),
                        new JSIntegerLiteral(0, typeof(Int32)),
                        TypeSystem.Boolean
                        );
                }
                else if (TypeUtil.IsNumeric(targetType))
                {
                    if (isNullable)
                    {
                        newExpression = new JSNullableCastExpression(ce.Expression, new JSType(targetType));
                    }
                    else if (
                        ce.Expression is JSCastExpression &&
                        (((JSCastExpression)ce.Expression).Expression.GetActualType(TypeSystem).MetadataType == MetadataType.Int64 ||
                         ((JSCastExpression)ce.Expression).Expression.GetActualType(TypeSystem).MetadataType == MetadataType.UInt64)
                        )
                    {
                        newExpression = ce.Expression;
                    }
                    else
                    {
                        newExpression = JSInvocationExpression.InvokeMethod(
                            JS.valueOf(targetType), ce.Expression, null, true
                            );
                    }
                }
                else if (targetType.FullName == "System.Enum")
                {
                    newExpression = ce.Expression;
                }
                else
                {
                    // Debugger.Break();
                }
            }
            else if (
                (targetType.MetadataType == MetadataType.Boolean) &&
                (ce.Expression is JSAsExpression) &&
                ((JSAsExpression)ce.Expression).GetActualType(TypeSystem) is GenericParameter
                )
            {
                // C# expressions such as (t is T) (where T is a generic parameter). See issue #150.
                // Tested with AsWithGenericParameter.cs
                newExpression = new JSBinaryOperatorExpression(
                    JSOperator.NotEqual,
                    ce.Expression, new JSNullLiteral(currentType),
                    TypeSystem.Boolean
                    );
            }
            else if (
                (targetType.MetadataType == MetadataType.Boolean) &&
                // A cast from Object to Boolean can occur in two forms:
                // An implied conversion, where an object expression is treated as a boolean (logicnot operation, etc).
                //  In this case, we want to do 'obj != null' to make it a boolean.
                // An explicit conversion, where an object expression is unboxed to boolean.
                //  In this case we want to leave it as-is.
                (ce.IsCoercion || (currentType.FullName != "System.Object"))
                )
            {
                newExpression = new JSBinaryOperatorExpression(
                    JSOperator.NotEqual,
                    ce.Expression, new JSDefaultValueLiteral(currentType),
                    TypeSystem.Boolean
                    );
            }
            else if (
                TypeUtil.IsNumeric(targetType) &&
                TypeUtil.IsNumeric(currentType) &&
                !TypeUtil.TypesAreEqual(targetType, currentType, true)
                )
            {
                TypeReference innerType = null;
                if (innerCast != null)
                {
                    innerType = innerCast.Expression.GetActualType(TypeSystem);
                }

                if (
                    TypeUtil.TypesAreAssignable(TypeInfo, targetType, innerType) &&
                    (
                        (TypeUtil.IsFloatingPoint(targetType) == TypeUtil.IsFloatingPoint(currentType)) &&
                        (TypeUtil.IsFloatingPoint(targetType) == TypeUtil.IsFloatingPoint(innerType))
                    ) &&
                    (TypeUtil.IsSigned(targetType) == TypeUtil.IsSigned(innerType)) &&
                    (TypeUtil.SizeOfType(targetType) <= TypeUtil.SizeOfType(currentType)) &&
                    (TypeUtil.SizeOfType(targetType) >= TypeUtil.SizeOfType(innerType))
                    )
                {
                    // HACK: Turn pointless conversions like '(int32)(int64)(1 + 2)' into '(1 + 2)'
                    newExpression = innerCast.Expression;
                }
                else if (currentType.MetadataType == MetadataType.Int64)
                {
                    if (!EmulateInt64)
                    {
                        newExpression = ce;
                    }
                    else if (targetType.MetadataType == MetadataType.UInt64)
                    {
                        newExpression = JSInvocationExpression
                                        .InvokeMethod(
                            TypeSystem.Int64,
                            new JSFakeMethod("ToUInt64", TypeSystem.UInt64, new TypeReference[] { }, MethodTypeFactory),
                            ce.Expression);
                    }
                    else
                    {
                        newExpression = JSInvocationExpression
                                        .InvokeMethod(
                            TypeSystem.Int64,
                            new JSFakeMethod("ToNumber", targetType, new TypeReference[] { TypeSystem.Double, TypeSystem.Boolean }, MethodTypeFactory),
                            ce.Expression,
                            GetInt64ConversionArgs(targetType));
                    }
                }
                else if (currentType.MetadataType == MetadataType.UInt64)
                {
                    if (!EmulateInt64)
                    {
                        newExpression = ce;
                    }
                    else if (targetType.MetadataType == MetadataType.Int64)
                    {
                        newExpression = JSInvocationExpression
                                        .InvokeMethod(
                            TypeSystem.Int64,
                            new JSFakeMethod("ToInt64", TypeSystem.Int64, new TypeReference[] { }, MethodTypeFactory),
                            ce.Expression);
                    }
                    else
                    {
                        newExpression = JSInvocationExpression
                                        .InvokeMethod(
                            TypeSystem.Int64,
                            new JSFakeMethod("ToNumber", targetType, new TypeReference[] { TypeSystem.Double, TypeSystem.Boolean }, MethodTypeFactory),
                            ce.Expression,
                            GetInt64ConversionArgs(targetType));
                    }
                }
                else if (targetType.MetadataType == MetadataType.Int64)
                {
                    if (!EmulateInt64)
                    {
                        newExpression = ce;
                    }
                    else
                    {
                        newExpression = JSInvocationExpression.InvokeStatic(
                            new JSType(TypeSystem.Int64),
                            new JSFakeMethod("FromNumber", TypeSystem.Int64, new[] { currentType }, MethodTypeFactory),
                            new[] { ce.Expression }, true
                            );
                    }
                }
                else if (targetType.MetadataType == MetadataType.UInt64)
                {
                    if (!EmulateInt64)
                    {
                        newExpression = ce;
                    }
                    else
                    {
                        newExpression = JSInvocationExpression.InvokeStatic(
                            new JSType(TypeSystem.UInt64),
                            new JSFakeMethod("FromNumber", TypeSystem.UInt64, new[] { currentType }, MethodTypeFactory),
                            new[] { ce.Expression }, true
                            );
                    }
                }
                else if (TypeUtil.IsIntegral(currentType))
                {
                    if (!TypeUtil.IsIntegral(targetType))
                    {
                        // Integer -> float conversion
                        newExpression = new JSIntegerToFloatExpression(ce.Expression, targetType);
                    }
                    else if (TypeUtil.SizeOfType(currentType) < TypeUtil.SizeOfType(targetType))
                    {
                        // Widening integer -> integer conversion
                        newExpression = ce.Expression;
                    }
                    else
                    {
                        newExpression = null;
                    }
                }
                else if (TypeUtil.IsIntegral(targetType))
                {
                    newExpression = new JSTruncateExpression(ce.Expression);
                }
                else if (TypeUtil.SizeOfType(targetType) < TypeUtil.SizeOfType(currentType))
                {
                    // Narrowing double -> float conversion
                    newExpression = new JSDoubleToFloatExpression(ce.Expression);
                }
                else
                {
                    // Widening float -> double conversion
                    newExpression = new JSFloatToDoubleExpression(ce.Expression);
                }
            }
            else
            {
                // newExpression = JSIL.Cast(ce.Expression, targetType);
            }

            if ((newExpression != null) && (newExpression != ce))
            {
                ParentNode.ReplaceChild(ce, newExpression);
                VisitReplacement(newExpression);
            }
            else
            {
                // Debugger.Break();
                VisitChildren(ce);
            }
        }
示例#11
0
        public void VisitNode(JSCastExpression ce)
        {
            var currentType = ce.Expression.GetActualType(TypeSystem);
            var targetType = ce.NewType;

            JSExpression newExpression = null;

            if (targetType.FullName == "System.ValueType") {
                var replacement = ce.Expression;
                ParentNode.ReplaceChild(ce, replacement);
                VisitReplacement(replacement);
                return;
            } else if (targetType.MetadataType == MetadataType.Char) {
                newExpression = JSInvocationExpression.InvokeStatic(
                    JS.fromCharCode, new[] { ce.Expression }, true
                );
            } else if (
                (currentType.MetadataType == MetadataType.Char) &&
                TypeUtil.IsIntegral(targetType)
            ) {
                newExpression = JSInvocationExpression.InvokeMethod(
                    JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true
                );
            } else if (
                IntroduceEnumCasts.IsEnumOrNullableEnum(currentType)
            ) {
                var enumInfo = TypeInfo.Get(currentType);
                var isNullable = TypeUtil.IsNullable(currentType);

                if (targetType.MetadataType == MetadataType.Boolean) {
                    EnumMemberInfo enumMember;
                    if (enumInfo.ValueToEnumMember.TryGetValue(0, out enumMember)) {
                        newExpression = new JSBinaryOperatorExpression(
                            JSOperator.NotEqual, ce.Expression,
                            new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean
                        );
                    } else if (enumInfo.ValueToEnumMember.TryGetValue(1, out enumMember)) {
                        newExpression = new JSBinaryOperatorExpression(
                            JSOperator.Equal, ce.Expression,
                            new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean
                        );
                    } else {
                        newExpression = new JSUntranslatableExpression(String.Format(
                            "Could not cast enum of type '{0}' to boolean because it has no zero value or one value",
                            currentType.FullName
                        ));
                    }
                } else if (TypeUtil.IsNumeric(targetType)) {
                    if (isNullable) {
                        newExpression = JSIL.ValueOfNullable(
                            ce.Expression
                        );
                    } else {
                        newExpression = JSInvocationExpression.InvokeMethod(
                            JS.valueOf(targetType), ce.Expression, null, true
                        );
                    }
                } else if (targetType.FullName == "System.Enum") {
                    newExpression = ce.Expression;
                } else {
                    // Debugger.Break();
                }
            } else if (
                (targetType.MetadataType == MetadataType.Boolean) &&
                // A cast from Object to Boolean can occur in two forms:
                // An implied conversion, where an object expression is treated as a boolean (logicnot operation, etc).
                //  In this case, we want to do 'obj != null' to make it a boolean.
                // An explicit conversion, where an object expression is unboxed to boolean.
                //  In this case we want to leave it as-is.
                (ce.IsCoercion || (currentType.FullName != "System.Object"))
            ) {
                JSLiteral nullLiteral;

                // HACK: Necessary because we represent Char instances as JS strings. Issue #150
                // Is this right?
                if (currentType.FullName == "System.Char")
                    nullLiteral = new JSDefaultValueLiteral(currentType);
                else
                    nullLiteral = new JSNullLiteral(currentType);

                newExpression = new JSBinaryOperatorExpression(
                    JSBinaryOperator.NotEqual,
                    ce.Expression, nullLiteral,
                    TypeSystem.Boolean
                );
            } else if (
                TypeUtil.IsNumeric(targetType) &&
                TypeUtil.IsNumeric(currentType) &&
                !TypeUtil.TypesAreEqual(targetType, currentType, true)
            ) {
                if (currentType.MetadataType == MetadataType.Int64) {
                    if (targetType.MetadataType == MetadataType.UInt64) {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToUInt64", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory),
                                ce.Expression);
                    }
                    else {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToNumber", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory),
                                ce.Expression);
                    }
                }
                else if (currentType.MetadataType == MetadataType.UInt64) {
                    if (targetType.MetadataType == MetadataType.Int64) {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToInt64", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory),
                                ce.Expression);
                    }
                    else {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToNumber", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory),
                                ce.Expression);
                    }
                }
                else if (targetType.MetadataType == MetadataType.Int64) {
                    newExpression = JSInvocationExpression.InvokeStatic(
                        new JSType(TypeSystem.Int64),
                        new JSFakeMethod("FromNumber", TypeSystem.Int64, new[] { currentType }, MethodTypeFactory),
                        new[] { ce.Expression },
                        true);
                }
                else if (targetType.MetadataType == MetadataType.UInt64) {
                    newExpression = JSInvocationExpression.InvokeStatic(
                        new JSType(TypeSystem.UInt64),
                        new JSFakeMethod("FromNumber", TypeSystem.UInt64, new[] { currentType }, MethodTypeFactory),
                        new[] { ce.Expression },
                        true);
                }
                else if (
                    TypeUtil.IsIntegral(currentType) ||
                    !TypeUtil.IsIntegral(targetType))
                {
                    newExpression = ce.Expression;
                }
                else
                {
                    newExpression = new JSTruncateExpression(ce.Expression);
                }
            } else {
                // newExpression = JSIL.Cast(ce.Expression, targetType);
            }

            if (newExpression != null) {
                ParentNode.ReplaceChild(ce, newExpression);
                VisitReplacement(newExpression);
            } else {
                // Debugger.Break();
                VisitChildren(ce);
            }
        }
示例#12
0
        public void VisitNode(JSCastExpression ce)
        {
            var currentType = ce.Expression.GetActualType(TypeSystem);
            var targetType  = ce.NewType;

            JSExpression newExpression = null;

            if (targetType.MetadataType == MetadataType.Char)
            {
                newExpression = JSInvocationExpression.InvokeStatic(
                    JS.fromCharCode, new[] { ce.Expression }, true
                    );
            }
            else if (
                (currentType.MetadataType == MetadataType.Char) &&
                TypeUtil.IsIntegral(targetType)
                )
            {
                newExpression = JSInvocationExpression.InvokeMethod(
                    JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true
                    );
            }
            else if (
                IntroduceEnumCasts.IsEnumOrNullableEnum(currentType)
                )
            {
                var enumInfo = TypeInfo.Get(currentType);

                if (targetType.MetadataType == MetadataType.Boolean)
                {
                    EnumMemberInfo enumMember;
                    if (enumInfo.ValueToEnumMember.TryGetValue(0, out enumMember))
                    {
                        newExpression = new JSBinaryOperatorExpression(
                            JSOperator.NotEqual, ce.Expression,
                            new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean
                            );
                    }
                    else if (enumInfo.ValueToEnumMember.TryGetValue(1, out enumMember))
                    {
                        newExpression = new JSBinaryOperatorExpression(
                            JSOperator.Equal, ce.Expression,
                            new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean
                            );
                    }
                    else
                    {
                        newExpression = new JSUntranslatableExpression(String.Format(
                                                                           "Could not cast enum of type '{0}' to boolean because it has no zero value or one value",
                                                                           currentType.FullName
                                                                           ));
                    }
                }
                else if (TypeUtil.IsNumeric(targetType))
                {
                    newExpression = JSInvocationExpression.InvokeStatic(
                        JS.Number(targetType), new[] { ce.Expression }, true
                        );
                }
                else if (targetType.FullName == "System.Enum")
                {
                    newExpression = ce.Expression;
                }
                else
                {
                    // Debugger.Break();
                }
            }
            else if (
                targetType.MetadataType == MetadataType.Boolean
                )
            {
                newExpression = new JSBinaryOperatorExpression(
                    JSBinaryOperator.NotEqual,
                    ce.Expression, new JSDefaultValueLiteral(currentType),
                    TypeSystem.Boolean
                    );
            }
            else if (
                TypeUtil.IsNumeric(targetType) &&
                TypeUtil.IsNumeric(currentType)
                )
            {
                if (
                    TypeUtil.IsIntegral(currentType) ||
                    !TypeUtil.IsIntegral(targetType)
                    )
                {
                    newExpression = ce.Expression;
                }
                else
                {
                    newExpression = JSInvocationExpression.InvokeStatic(JS.floor, new[] { ce.Expression }, true);
                }
            }
            else
            {
                newExpression = JSIL.Cast(ce.Expression, targetType);
            }

            if (newExpression != null)
            {
                ParentNode.ReplaceChild(ce, newExpression);
                VisitReplacement(newExpression);
            }
            else
            {
                // Debugger.Break();
                VisitChildren(ce);
            }
        }
示例#13
0
        public void VisitNode(JSCastExpression cast)
        {
            var ct = GetCachedType(cast.NewType);
            if (ct != null)
                cast.CachedTypeIndex = ct.Index;

            VisitChildren(cast);
        }
示例#14
0
        public void VisitNode(JSBinaryOperatorExpression boe)
        {
            var leftType     = boe.Left.GetActualType(TypeSystem);
            var leftIsEnum   = IsEnumOrNullableEnum(leftType);
            var rightType    = boe.Right.GetActualType(TypeSystem);
            var rightIsEnum  = IsEnumOrNullableEnum(rightType);
            var resultType   = boe.GetActualType(TypeSystem);
            var resultIsEnum = IsEnumOrNullableEnum(resultType);

            var eitherIsEnum = leftIsEnum || rightIsEnum;

            var assignmentOperator = boe.Operator as JSAssignmentOperator;
            JSBinaryOperator replacementOperator;

            if (LogicalOperators.Contains(boe.Operator))
            {
                if (eitherIsEnum)
                {
                    if (leftIsEnum)
                    {
                        var cast = JSInvocationExpression.InvokeMethod(
                            JS.valueOf(TypeSystem.Int32), boe.Left, null, true
                            );

                        boe.ReplaceChild(boe.Left, cast);
                    }

                    if (rightIsEnum)
                    {
                        var cast = JSInvocationExpression.InvokeMethod(
                            JS.valueOf(TypeSystem.Int32), boe.Right, null, true
                            );

                        boe.ReplaceChild(boe.Right, cast);
                    }
                }
            }
            else if (BitwiseOperators.Contains(boe.Operator))
            {
                var parentCast = ParentNode as JSCastExpression;
                if (resultIsEnum && ((parentCast == null) || (parentCast.NewType != resultType)))
                {
                    var cast = JSCastExpression.New(
                        boe, resultType, TypeSystem, true
                        );

                    ParentNode.ReplaceChild(boe, cast);
                    VisitReplacement(cast);
                }
            }
            else if (
                (assignmentOperator != null) &&
                ReverseCompoundAssignments.TryGetValue(assignmentOperator, out replacementOperator) &&
                leftIsEnum
                )
            {
                var replacement = new JSBinaryOperatorExpression(
                    JSOperator.Assignment, boe.Left,
                    JSCastExpression.New(
                        new JSBinaryOperatorExpression(
                            replacementOperator, boe.Left, boe.Right, TypeSystem.Int32
                            ), leftType, TypeSystem, true
                        ),
                    leftType
                    );

                ParentNode.ReplaceChild(boe, replacement);
                VisitReplacement(replacement);
                return;
            }

            VisitChildren(boe);
        }
示例#15
0
        public void VisitNode(JSCastExpression ce)
        {
            var currentType = ce.Expression.GetActualType(TypeSystem);
            var targetType = ce.NewType;

            JSExpression newExpression = null;

            if (targetType.FullName == "System.ValueType") {
                var replacement = ce.Expression;
                ParentNode.ReplaceChild(ce, replacement);
                VisitReplacement(replacement);
                return;
            } else if (targetType.MetadataType == MetadataType.Char) {
                newExpression = JSInvocationExpression.InvokeStatic(
                    JS.fromCharCode, new[] { ce.Expression }, true
                );
            } else if (
                (currentType.MetadataType == MetadataType.Char) &&
                TypeUtil.IsIntegral(targetType)
            ) {
                newExpression = JSInvocationExpression.InvokeMethod(
                    JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true
                );
            } else if (
                IntroduceEnumCasts.IsEnumOrNullableEnum(currentType)
            ) {
                TypeInfo enumInfo;
                var isNullable = TypeUtil.IsNullable(currentType);

                if (isNullable) {
                    int temp;
                    var git = (GenericInstanceType)TypeUtil.FullyDereferenceType(currentType, out temp);
                    enumInfo = TypeInfo.Get(git.GenericArguments[0]);
                } else {
                    enumInfo = TypeInfo.Get(currentType);
                }

                if (enumInfo == null)
                    throw new InvalidOperationException("Unable to extract enum type from typereference " + currentType);

                if (targetType.MetadataType == MetadataType.Boolean) {
                    EnumMemberInfo enumMember;
                    if (enumInfo.ValueToEnumMember.TryGetValue(0, out enumMember)) {
                        newExpression = new JSBinaryOperatorExpression(
                            JSOperator.NotEqual, ce.Expression,
                            new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean
                        );
                    } else if (enumInfo.ValueToEnumMember.TryGetValue(1, out enumMember)) {
                        newExpression = new JSBinaryOperatorExpression(
                            JSOperator.Equal, ce.Expression,
                            new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean
                        );
                    } else {
                        newExpression = new JSUntranslatableExpression(String.Format(
                            "Could not cast enum of type '{0}' to boolean because it has no zero value or one value",
                            currentType.FullName
                        ));
                    }
                } else if (TypeUtil.IsNumeric(targetType)) {
                    if (isNullable) {
                        newExpression = JSIL.ValueOfNullable(
                            ce.Expression
                        );
                    } else if (
                        ce.Expression is JSCastExpression &&
                        (((JSCastExpression)ce.Expression).Expression.GetActualType(TypeSystem).MetadataType == MetadataType.Int64 ||
                        ((JSCastExpression)ce.Expression).Expression.GetActualType(TypeSystem).MetadataType == MetadataType.UInt64)
                    ) {
                        newExpression = ce.Expression;
                    } else {
                        newExpression = JSInvocationExpression.InvokeMethod(
                            JS.valueOf(targetType), ce.Expression, null, true
                        );
                    }
                } else if (targetType.FullName == "System.Enum") {
                    newExpression = ce.Expression;
                } else {
                    // Debugger.Break();
                }
            } else if (
                (targetType.MetadataType == MetadataType.Boolean) &&
                (ce.Expression is JSAsExpression) &&
                ((JSAsExpression)ce.Expression).GetActualType(TypeSystem) is GenericParameter
            ) {
                // C# expressions such as (t is T) (where T is a generic parameter). See issue #150.
                // Tested with AsWithGenericParameter.cs
                newExpression = new JSBinaryOperatorExpression(
                    JSBinaryOperator.NotEqual,
                    ce.Expression, new JSNullLiteral(currentType),
                    TypeSystem.Boolean
                );
            }
            else if (
                (targetType.MetadataType == MetadataType.Boolean) &&
                // A cast from Object to Boolean can occur in two forms:
                // An implied conversion, where an object expression is treated as a boolean (logicnot operation, etc).
                //  In this case, we want to do 'obj != null' to make it a boolean.
                // An explicit conversion, where an object expression is unboxed to boolean.
                //  In this case we want to leave it as-is.
                (ce.IsCoercion || (currentType.FullName != "System.Object"))
            ) {
                newExpression = new JSBinaryOperatorExpression(
                    JSBinaryOperator.NotEqual,
                    ce.Expression, new JSDefaultValueLiteral(currentType),
                    TypeSystem.Boolean
                );
            } else if (
                TypeUtil.IsNumeric(targetType) &&
                TypeUtil.IsNumeric(currentType) &&
                !TypeUtil.TypesAreEqual(targetType, currentType, true)
            ) {
                if (currentType.MetadataType == MetadataType.Int64) {
                    if (targetType.MetadataType == MetadataType.UInt64) {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToUInt64", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory),
                                ce.Expression);
                    }
                    else {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToNumber", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory),
                                ce.Expression);
                    }
                }
                else if (currentType.MetadataType == MetadataType.UInt64) {
                    if (targetType.MetadataType == MetadataType.Int64) {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToInt64", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory),
                                ce.Expression);
                    }
                    else {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToNumber", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory),
                                ce.Expression);
                    }
                }
                else if (targetType.MetadataType == MetadataType.Int64) {
                    newExpression = JSInvocationExpression.InvokeStatic(
                        new JSType(TypeSystem.Int64),
                        new JSFakeMethod("FromNumber", TypeSystem.Int64, new[] { currentType }, MethodTypeFactory),
                        new[] { ce.Expression },
                        true);
                }
                else if (targetType.MetadataType == MetadataType.UInt64) {
                    newExpression = JSInvocationExpression.InvokeStatic(
                        new JSType(TypeSystem.UInt64),
                        new JSFakeMethod("FromNumber", TypeSystem.UInt64, new[] { currentType }, MethodTypeFactory),
                        new[] { ce.Expression },
                        true);
                }
                else if (
                    TypeUtil.IsIntegral(currentType) ||
                    !TypeUtil.IsIntegral(targetType))
                {
                    newExpression = ce.Expression;
                }
                else
                {
                    newExpression = new JSTruncateExpression(ce.Expression);
                }
            } else {
                // newExpression = JSIL.Cast(ce.Expression, targetType);
            }

            if (newExpression != null) {
                ParentNode.ReplaceChild(ce, newExpression);
                VisitReplacement(newExpression);
            } else {
                // Debugger.Break();
                VisitChildren(ce);
            }
        }
示例#16
0
        public void VisitNode(JSCastExpression ce)
        {
            var currentType = ce.Expression.GetActualType(TypeSystem);
            var targetType  = ce.NewType;

            JSExpression newExpression = null;

            if (targetType.FullName == "System.ValueType")
            {
                var replacement = ce.Expression;
                ParentNode.ReplaceChild(ce, replacement);
                VisitReplacement(replacement);
                return;
            }
            else if (targetType.MetadataType == MetadataType.Char)
            {
                newExpression = JSInvocationExpression.InvokeStatic(
                    JS.fromCharCode, new[] { ce.Expression }, true
                    );
            }
            else if (
                (currentType.MetadataType == MetadataType.Char) &&
                TypeUtil.IsIntegral(targetType)
                )
            {
                newExpression = JSInvocationExpression.InvokeMethod(
                    JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true
                    );
            }
            else if (
                IntroduceEnumCasts.IsEnumOrNullableEnum(currentType)
                )
            {
                var enumInfo   = TypeInfo.Get(currentType);
                var isNullable = TypeUtil.IsNullable(currentType);

                if (targetType.MetadataType == MetadataType.Boolean)
                {
                    EnumMemberInfo enumMember;
                    if (enumInfo.ValueToEnumMember.TryGetValue(0, out enumMember))
                    {
                        newExpression = new JSBinaryOperatorExpression(
                            JSOperator.NotEqual, ce.Expression,
                            new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean
                            );
                    }
                    else if (enumInfo.ValueToEnumMember.TryGetValue(1, out enumMember))
                    {
                        newExpression = new JSBinaryOperatorExpression(
                            JSOperator.Equal, ce.Expression,
                            new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean
                            );
                    }
                    else
                    {
                        newExpression = new JSUntranslatableExpression(String.Format(
                                                                           "Could not cast enum of type '{0}' to boolean because it has no zero value or one value",
                                                                           currentType.FullName
                                                                           ));
                    }
                }
                else if (TypeUtil.IsNumeric(targetType))
                {
                    if (isNullable)
                    {
                        newExpression = JSIL.ValueOfNullable(
                            ce.Expression
                            );
                    }
                    else
                    {
                        newExpression = JSInvocationExpression.InvokeMethod(
                            JS.valueOf(targetType), ce.Expression, null, true
                            );
                    }
                }
                else if (targetType.FullName == "System.Enum")
                {
                    newExpression = ce.Expression;
                }
                else
                {
                    // Debugger.Break();
                }
            }
            else if (
                (targetType.MetadataType == MetadataType.Boolean) &&
                // A cast from Object to Boolean can occur in two forms:
                // An implied conversion, where an object expression is treated as a boolean (logicnot operation, etc).
                //  In this case, we want to do 'obj != null' to make it a boolean.
                // An explicit conversion, where an object expression is unboxed to boolean.
                //  In this case we want to leave it as-is.
                (ce.IsCoercion || (currentType.FullName != "System.Object"))
                )
            {
                newExpression = new JSBinaryOperatorExpression(
                    JSBinaryOperator.NotEqual,
                    ce.Expression, new JSDefaultValueLiteral(currentType),
                    TypeSystem.Boolean
                    );
            }
            else if (
                TypeUtil.IsNumeric(targetType) &&
                TypeUtil.IsNumeric(currentType)
                )
            {
                if (
                    TypeUtil.IsIntegral(currentType) ||
                    !TypeUtil.IsIntegral(targetType)
                    )
                {
                    newExpression = ce.Expression;
                }
                else
                {
                    newExpression = new JSTruncateExpression(ce.Expression);
                }
            }
            else
            {
                // newExpression = JSIL.Cast(ce.Expression, targetType);
            }

            if (newExpression != null)
            {
                ParentNode.ReplaceChild(ce, newExpression);
                VisitReplacement(newExpression);
            }
            else
            {
                // Debugger.Break();
                VisitChildren(ce);
            }
        }