예제 #1
0
        public static void ClipInteger(ConversionBlock block, Expression expression, IType type, bool isExplicit)
        {
            var specialType = NullableType.IsNullable(type) ? NullableType.GetUnderlyingType(type) : type;

            if (!isExplicit && (specialType.IsKnownType(KnownTypeCode.UInt64) || specialType.IsKnownType(KnownTypeCode.Int64)))
            {
                //expression.AcceptVisitor(block.Emitter);
                return;
            }

            NarrowingNumericOrEnumerationConversion(block, expression, specialType, false, false, NullableType.IsNullable(type), isExplicit);
        }
예제 #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(JS.Types.SYSTEM_DECIMAL + ".toFloat");
                block.Write("(");
                block.AfterOutput += ")";
            }
            else
            {
                block.Write(JS.Types.SYSTEM_DECIMAL + ".toInt(");
                block.AfterOutput = ", " + BridgeTypes.ToJsName(expectedType, block.Emitter) + ")";
            }
        }
예제 #3
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;

                return(ConversionBlock.DoConversion(block, expression, conversion, expectedType, level, rr));
            }
            catch
            {
            }

            return(0);
        }
예제 #4
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) + ")";
            }
        }
예제 #5
0
        private static void AddBox(IMember m, IEmitter emitter, JObject properties)
        {
            bool needBox = ConversionBlock.IsBoxable(m.ReturnType, emitter) ||
                           m.ReturnType.IsKnownType(KnownTypeCode.NullableOfT) &&
                           ConversionBlock.IsBoxable(NullableType.GetUnderlyingType(m.ReturnType), emitter);

            if (needBox)
            {
                StringBuilder sb = new StringBuilder("function (" + JS.Vars.V + ") { return ");

                sb.Append(JS.Types.Bridge.BOX);
                sb.Append("(" + JS.Vars.V + ", ");
                sb.Append(ConversionBlock.GetBoxedType(m.ReturnType, emitter));

                var inlineMethod = ConversionBlock.GetInlineMethod(emitter, CS.Methods.TOSTRING,
                                                                   emitter.Resolver.Compilation.FindType(KnownTypeCode.String), m.ReturnType, null);

                if (inlineMethod != null)
                {
                    sb.Append(", " + inlineMethod);
                }

                inlineMethod = ConversionBlock.GetInlineMethod(emitter, CS.Methods.GETHASHCODE,
                                                               emitter.Resolver.Compilation.FindType(KnownTypeCode.Int32), m.ReturnType, null);

                if (inlineMethod != null)
                {
                    sb.Append(", " + inlineMethod);
                }

                sb.Append(");");

                sb.Append("}");
                properties.Add(JS.Fields.BOX, new JRaw(sb.ToString()));
            }
        }
예제 #6
0
 protected virtual int CheckConversion(Expression expression)
 {
     return(ConversionBlock.CheckConversion(this, expression));
 }
예제 #7
0
 public static void FloatToInt(ConversionBlock block, Expression expression, IType sourceType, IType targetType, bool isChecked)
 {
     NarrowingNumericOrEnumerationConversion(block, expression, NullableType.IsNullable(targetType) ? NullableType.GetUnderlyingType(targetType) : targetType, true, isChecked, NullableType.IsNullable(sourceType));
 }
예제 #8
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 += ")";
                }
            }
        }
예제 #9
0
        protected virtual void EmitCastExpression(Expression expression, AstType type, string method)
        {
            var castToEnum = this.Emitter.BridgeTypes.ToType(type).Kind == TypeKind.Enum;

            if (method != Bridge.Translator.Emitter.IS && (Helpers.IsIgnoreCast(type, this.Emitter) || castToEnum))
            {
                expression.AcceptVisitor(this.Emitter);
                return;
            }

            if (method == Bridge.Translator.Emitter.IS && castToEnum)
            {
                this.Write("Bridge.hasValue(");
                expression.AcceptVisitor(this.Emitter);
                this.Write(")");
                return;
            }

            var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter);
            var typerr       = this.Emitter.Resolver.ResolveNode(type, this.Emitter);

            if (expressionrr.Type.Equals(typerr.Type))
            {
                if (method == Bridge.Translator.Emitter.IS)
                {
                    this.WriteScript(true);
                }
                else
                {
                    expression.AcceptVisitor(this.Emitter);
                }

                return;
            }

            bool   isInlineCast;
            string castCode         = this.GetCastCode(expression, type, out isInlineCast);
            bool   isNullable       = NullableType.IsNullable(expressionrr.Type);
            bool   isResultNullable = NullableType.IsNullable(typerr.Type);

            if (isInlineCast)
            {
                if (isNullable)
                {
                    isNullable = !NullableType.GetUnderlyingType(expressionrr.Type).Equals(typerr.Type);
                }

                this.EmitInlineCast(expression, type, castCode, isNullable, isResultNullable);
                return;
            }

            if (method == Bridge.Translator.Emitter.CAST)
            {
                if (Helpers.IsIntegerType(typerr.Type, this.Emitter.Resolver))
                {
                    if (expressionrr.Type != null && Helpers.IsFloatType(expressionrr.Type, this.Emitter.Resolver))
                    {
                        this.Write("Bridge.Int.trunc(");
                        if (isNullable && !isResultNullable)
                        {
                            this.Write("Bridge.Nullable.getValue(");
                        }
                        expression.AcceptVisitor(this.Emitter);
                        if (isNullable && !isResultNullable)
                        {
                            this.WriteCloseParentheses();
                        }
                        this.Write(")");

                        return;
                    }
                }

                if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression))
                {
                    expression.AcceptVisitor(this.Emitter);

                    return;
                }
            }

            var  simpleType = type as SimpleType;
            bool hasValue   = false;

            if (simpleType != null && simpleType.Identifier == "dynamic")
            {
                if (method == Bridge.Translator.Emitter.CAST || method == Bridge.Translator.Emitter.AS)
                {
                    expression.AcceptVisitor(this.Emitter);
                    return;
                }
                else if (method == Bridge.Translator.Emitter.IS)
                {
                    hasValue = true;
                    method   = "hasValue";
                }
            }

            this.Write(Bridge.Translator.Emitter.ROOT);
            this.WriteDot();
            this.Write(method);
            this.WriteOpenParentheses();
            if (isNullable && !isResultNullable)
            {
                this.Write("Bridge.Nullable.getValue(");
            }
            expression.AcceptVisitor(this.Emitter);
            if (isNullable && !isResultNullable)
            {
                this.WriteCloseParentheses();
            }

            if (!hasValue)
            {
                this.WriteComma();

                if (castCode != null)
                {
                    this.Write(castCode);
                }
                else
                {
                    this.EmitCastType(type);
                }
            }

            if (isResultNullable && method != Bridge.Translator.Emitter.IS)
            {
                this.WriteComma();
                this.WriteScript(true);
            }

            this.WriteCloseParentheses();
        }
예제 #10
0
파일: CastBlock.cs 프로젝트: wushian/Bridge
        protected virtual void EmitCastExpression(Expression expression, AstType type, string method)
        {
            var castToEnum = this.Emitter.BridgeTypes.ToType(type).Kind == TypeKind.Enum;

            if (method != Bridge.Translator.Emitter.IS && (Helpers.IsIgnoreCast(type, this.Emitter) || castToEnum))
            {
                expression.AcceptVisitor(this.Emitter);
                return;
            }

            if (method == Bridge.Translator.Emitter.CAST)
            {
                var cast_rr = this.Emitter.Resolver.ResolveNode(this.CastExpression, this.Emitter);

                if (cast_rr is ConstantResolveResult)
                {
                    var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression);
                    var value        = ((ConstantResolveResult)cast_rr).ConstantValue;

                    this.WriteCastValue(value, expectedType);
                    return;
                }
                else
                {
                    var conv_rr = cast_rr as ConversionResolveResult;
                    if (conv_rr != null && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined)
                    {
                        var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression);
                        var value        = ((ConstantResolveResult)conv_rr.Input).ConstantValue;
                        this.WriteCastValue(value, expectedType);
                        return;
                    }
                }
            }

            if (method == Bridge.Translator.Emitter.IS && castToEnum)
            {
                this.Write("Bridge.hasValue(");
                expression.AcceptVisitor(this.Emitter);
                this.Write(")");
                return;
            }

            var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter);
            var typerr       = this.Emitter.Resolver.ResolveNode(type, this.Emitter);

            if (expressionrr.Type.Equals(typerr.Type))
            {
                if (method == Bridge.Translator.Emitter.IS)
                {
                    this.WriteScript(true);
                }
                else
                {
                    expression.AcceptVisitor(this.Emitter);
                }

                return;
            }

            bool   isInlineCast;
            string castCode         = this.GetCastCode(expression, type, out isInlineCast);
            bool   isNullable       = NullableType.IsNullable(expressionrr.Type);
            bool   isResultNullable = NullableType.IsNullable(typerr.Type);

            if (isInlineCast)
            {
                this.EmitInlineCast(expression, type, castCode);
                return;
            }

            bool isCast = method == Bridge.Translator.Emitter.CAST;

            if (isCast)
            {
                if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression) || ConversionBlock.IsUserDefinedConversion(this, this.CastExpression))
                {
                    expression.AcceptVisitor(this.Emitter);

                    return;
                }
            }

            var conversion = this.Emitter.Resolver.Resolver.GetConversion(expression);

            if (conversion.IsNumericConversion || (isCast && conversion.IsIdentityConversion))
            {
                expression.AcceptVisitor(this.Emitter);
                return;
            }

            var  simpleType = type as SimpleType;
            bool hasValue   = false;

            if (simpleType != null && simpleType.Identifier == "dynamic")
            {
                if (method == Bridge.Translator.Emitter.CAST || method == Bridge.Translator.Emitter.AS)
                {
                    expression.AcceptVisitor(this.Emitter);
                    return;
                }
                else if (method == Bridge.Translator.Emitter.IS)
                {
                    hasValue = true;
                    method   = "hasValue";
                }
            }

            this.Write(Bridge.Translator.Emitter.ROOT);
            this.WriteDot();
            this.Write(method);
            this.WriteOpenParentheses();

            expression.AcceptVisitor(this.Emitter);

            if (!hasValue)
            {
                this.WriteComma();

                if (castCode != null)
                {
                    this.Write(castCode);
                }
                else
                {
                    this.EmitCastType(type);
                }
            }

            if (isResultNullable && method != Bridge.Translator.Emitter.IS)
            {
                this.WriteComma();
                this.WriteScript(true);
            }

            this.WriteCloseParentheses();
        }
예제 #11
0
        protected void VisitAssignmentExpression()
        {
            AssignmentExpression assignmentExpression = this.AssignmentExpression;
            var    oldAssigment     = this.Emitter.IsAssignment;
            var    oldAssigmentType = this.Emitter.AssignmentType;
            string variable         = null;

            bool needReturnValue = !(assignmentExpression.Parent is ExpressionStatement);

            if (needReturnValue && assignmentExpression.Parent is LambdaExpression)
            {
                var lambdarr = this.Emitter.Resolver.ResolveNode(assignmentExpression.Parent, this.Emitter) as LambdaResolveResult;

                if (lambdarr != null && lambdarr.ReturnType.Kind == TypeKind.Void)
                {
                    needReturnValue = false;
                }
            }

            var  delegateAssigment = false;
            bool isEvent           = false;
            var  initCount         = this.Emitter.Writers.Count;

            var asyncExpressionHandling = this.Emitter.AsyncExpressionHandling;

            this.WriteAwaiters(assignmentExpression.Left);
            this.WriteAwaiters(assignmentExpression.Right);

            var  leftResolverResult  = this.Emitter.Resolver.ResolveNode(assignmentExpression.Left, this.Emitter);
            var  rightResolverResult = this.Emitter.Resolver.ResolveNode(assignmentExpression.Right, this.Emitter);
            var  rr                = this.Emitter.Resolver.ResolveNode(assignmentExpression, this.Emitter);
            var  orr               = rr as OperatorResolveResult;
            bool isDecimal         = Helpers.IsDecimalType(rr.Type, this.Emitter.Resolver);
            bool isLong            = Helpers.Is64Type(rr.Type, this.Emitter.Resolver);
            var  expectedType      = this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression);
            bool isDecimalExpected = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver);
            bool isLongExpected    = Helpers.Is64Type(expectedType, this.Emitter.Resolver);
            bool isUserOperator    = this.IsUserOperator(orr);

            bool isUint = rr.Type.IsKnownType(KnownTypeCode.UInt16) ||
                          rr.Type.IsKnownType(KnownTypeCode.UInt32) ||
                          rr.Type.IsKnownType(KnownTypeCode.UInt64);

            var charToString = -1;

            if (orr != null && orr.Type.IsKnownType(KnownTypeCode.String))
            {
                for (int i = 0; i < orr.Operands.Count; i++)
                {
                    var crr = orr.Operands[i] as ConversionResolveResult;
                    if (crr != null && crr.Input.Type.IsKnownType(KnownTypeCode.Char))
                    {
                        charToString = i;
                    }
                }
            }

            var  memberTargetrr = leftResolverResult as MemberResolveResult;
            bool isField        = (memberTargetrr != null && memberTargetrr.Member is IField &&
                                   (memberTargetrr.TargetResult is ThisResolveResult ||
                                    memberTargetrr.TargetResult is LocalResolveResult)) || leftResolverResult is ThisResolveResult || leftResolverResult is LocalResolveResult || leftResolverResult is ConstantResolveResult;

            var  rightMemberTargetrr = rightResolverResult as MemberResolveResult;
            bool isRightSimple       = (rightMemberTargetrr != null && rightMemberTargetrr.Member is IField &&
                                        (rightMemberTargetrr.TargetResult is ThisResolveResult ||
                                         rightMemberTargetrr.TargetResult is LocalResolveResult)) || rightResolverResult is ThisResolveResult || rightResolverResult is LocalResolveResult || rightResolverResult is ConstantResolveResult;

            var needTempVar = needReturnValue && (!isRightSimple && !isField || assignmentExpression.Operator != AssignmentOperatorType.Assign);

            /*if (assignmentExpression.Operator == AssignmentOperatorType.Any)
             * {
             *  needTempVar = false;
             * }*/

            if (needReturnValue)
            {
                if (needTempVar)
                {
                    variable = this.GetTempVarName();
                    this.Write("(" + variable + " = ");

                    var oldValue1 = this.Emitter.ReplaceAwaiterByVar;
                    this.Emitter.ReplaceAwaiterByVar = true;
                    assignmentExpression.Right.AcceptVisitor(this.Emitter);

                    this.Emitter.ReplaceAwaiterByVar = oldValue1;
                    this.Write(", ");
                }
                else
                {
                    this.Write("(");
                }
            }

            if (assignmentExpression.Operator == AssignmentOperatorType.Divide &&
                !(this.Emitter.IsJavaScriptOverflowMode && !ConversionBlock.InsideOverflowContext(this.Emitter, assignmentExpression)) &&
                !isLong && !isLongExpected &&
                (
                    (Helpers.IsIntegerType(leftResolverResult.Type, this.Emitter.Resolver) &&
                     Helpers.IsIntegerType(rightResolverResult.Type, this.Emitter.Resolver)) ||

                    (Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Left), this.Emitter.Resolver) &&
                     Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Right), this.Emitter.Resolver))
                ))
            {
                this.Emitter.IsAssignment   = true;
                this.Emitter.AssignmentType = AssignmentOperatorType.Assign;
                var oldValue1 = this.Emitter.ReplaceAwaiterByVar;
                this.Emitter.ReplaceAwaiterByVar = true;
                assignmentExpression.Left.AcceptVisitor(this.Emitter);

                if (this.Emitter.Writers.Count == initCount)
                {
                    this.Write(" = ");
                }

                this.Emitter.ReplaceAwaiterByVar = oldValue1;
                this.Emitter.AssignmentType      = oldAssigmentType;
                this.Emitter.IsAssignment        = oldAssigment;

                this.Write(JS.Types.BRIDGE_INT + "." + JS.Funcs.Math.DIV + "(");
                assignmentExpression.Left.AcceptVisitor(this.Emitter);
                this.Write(", ");
                oldValue1 = this.Emitter.ReplaceAwaiterByVar;
                this.Emitter.ReplaceAwaiterByVar = true;

                assignmentExpression.Right.AcceptVisitor(this.Emitter);

                this.Write(")");

                this.Emitter.ReplaceAwaiterByVar     = oldValue1;
                this.Emitter.AsyncExpressionHandling = asyncExpressionHandling;

                if (this.Emitter.Writers.Count > initCount)
                {
                    this.PopWriter();
                }

                if (needReturnValue && !isField)
                {
                    if (needTempVar)
                    {
                        this.Write(", " + variable);
                    }
                    else
                    {
                        this.Write(", ");
                        this.Emitter.IsAssignment = false;
                        assignmentExpression.Right.AcceptVisitor(this.Emitter);
                        this.Emitter.IsAssignment = oldAssigment;
                    }
                }

                if (needReturnValue)
                {
                    this.Write(")");
                }

                return;
            }

            if (assignmentExpression.Operator == AssignmentOperatorType.Add ||
                assignmentExpression.Operator == AssignmentOperatorType.Subtract)
            {
                var add = assignmentExpression.Operator == AssignmentOperatorType.Add;

                if (this.Emitter.Validator.IsDelegateOrLambda(leftResolverResult))
                {
                    delegateAssigment = true;
                    var leftMemberResolveResult = leftResolverResult as MemberResolveResult;

                    if (leftMemberResolveResult != null)
                    {
                        isEvent = leftMemberResolveResult.Member is IEvent;
                    }

                    if (!isEvent)
                    {
                        this.Emitter.IsAssignment   = true;
                        this.Emitter.AssignmentType = AssignmentOperatorType.Assign;
                        assignmentExpression.Left.AcceptVisitor(this.Emitter);
                        this.Emitter.IsAssignment = false;

                        if (this.Emitter.Writers.Count == initCount)
                        {
                            this.Write(" = ");
                        }

                        this.Write(add ? JS.Funcs.BRIDGE_COMBINE : JS.Funcs.BRIDGE_REMOVE);
                        this.WriteOpenParentheses();
                    }
                }
            }

            bool   nullable = orr != null && orr.IsLiftedOperator;
            string root     = JS.Types.SYSTEM_NULLABLE + ".";

            bool special = nullable;

            this.Emitter.IsAssignment   = true;
            this.Emitter.AssignmentType = assignmentExpression.Operator;
            var oldValue = this.Emitter.ReplaceAwaiterByVar;

            this.Emitter.ReplaceAwaiterByVar = true;

            bool thisAssignment = leftResolverResult is ThisResolveResult;

            if (!thisAssignment)
            {
                if (special || (isDecimal && isDecimalExpected) || (isLong && isLongExpected) || isUserOperator)
                {
                    this.Emitter.AssignmentType = AssignmentOperatorType.Assign;
                }

                if (delegateAssigment && !isEvent)
                {
                    this.Emitter.IsAssignment = false;
                }

                assignmentExpression.Left.AcceptVisitor(this.Emitter);

                if (delegateAssigment)
                {
                    this.Emitter.IsAssignment = true;
                }
            }
            else
            {
                this.Write("(");
            }

            this.Emitter.ReplaceAwaiterByVar = oldValue;
            this.Emitter.AssignmentType      = oldAssigmentType;
            this.Emitter.IsAssignment        = oldAssigment;

            if (this.Emitter.Writers.Count == initCount && !delegateAssigment && !thisAssignment)
            {
                this.WriteSpace();
            }

            if (isDecimal && isDecimalExpected)
            {
                if (this.Emitter.Writers.Count == initCount)
                {
                    this.Write("= ");
                }

                oldValue = this.Emitter.ReplaceAwaiterByVar;
                this.Emitter.ReplaceAwaiterByVar = true;

                this.HandleDecimal(rr, variable);

                if (this.Emitter.Writers.Count > initCount)
                {
                    this.PopWriter();
                }

                if (needTempVar)
                {
                    this.Write(", " + variable + ")");
                }
                else if (needReturnValue)
                {
                    if (!isField)
                    {
                        this.Write(", ");
                        this.Emitter.IsAssignment = false;
                        assignmentExpression.Right.AcceptVisitor(this.Emitter);
                        this.Emitter.IsAssignment = oldAssigment;
                    }

                    this.Write(")");
                }

                this.Emitter.ReplaceAwaiterByVar = oldValue;
                return;
            }

            if (isLong && isLongExpected)
            {
                if (this.Emitter.Writers.Count == initCount)
                {
                    this.Write("= ");
                }

                oldValue = this.Emitter.ReplaceAwaiterByVar;
                this.Emitter.ReplaceAwaiterByVar = true;

                this.HandleLong(rr, variable, isUint);

                if (this.Emitter.Writers.Count > initCount)
                {
                    this.PopWriter();
                }

                if (needTempVar)
                {
                    this.Write(", " + variable + ")");
                }
                else if (needReturnValue)
                {
                    if (!isField)
                    {
                        this.Write(", ");
                        this.Emitter.IsAssignment = false;
                        assignmentExpression.Right.AcceptVisitor(this.Emitter);
                        this.Emitter.IsAssignment = oldAssigment;
                    }

                    this.Write(")");
                }
                this.Emitter.ReplaceAwaiterByVar = oldValue;
                return;
            }

            if (this.ResolveOperator(assignmentExpression, orr, initCount, thisAssignment))
            {
                if (thisAssignment)
                {
                    this.Write(")." + JS.Funcs.CLONE + "(this)");
                }
                else if (needReturnValue)
                {
                    this.Write(")");
                }
                return;
            }

            bool isBool = NullableType.IsNullable(rr.Type) ? NullableType.GetUnderlyingType(rr.Type).IsKnownType(KnownTypeCode.Boolean) : rr.Type.IsKnownType(KnownTypeCode.Boolean);

            if (!delegateAssigment)
            {
                if (!special)
                {
                    switch (assignmentExpression.Operator)
                    {
                    case AssignmentOperatorType.Assign:
                        break;

                    case AssignmentOperatorType.Add:
                        this.Write("+");
                        break;

                    case AssignmentOperatorType.BitwiseAnd:
                        if (!isBool)
                        {
                            this.Write("&");
                        }
                        break;

                    case AssignmentOperatorType.BitwiseOr:
                        if (!isBool)
                        {
                            this.Write("|");
                        }

                        break;

                    case AssignmentOperatorType.Divide:
                        this.Write("/");
                        break;

                    case AssignmentOperatorType.ExclusiveOr:
                        this.Write("^");
                        break;

                    case AssignmentOperatorType.Modulus:
                        this.Write("%");
                        break;

                    case AssignmentOperatorType.Multiply:
                        this.Write("*");
                        break;

                    case AssignmentOperatorType.ShiftLeft:
                        this.Write("<<");
                        break;

                    case AssignmentOperatorType.ShiftRight:
                        this.Write(isUint ? ">>>" : ">>");
                        break;

                    case AssignmentOperatorType.Subtract:
                        this.Write("-");
                        break;

                    default:
                        throw new EmitterException(assignmentExpression,
                                                   "Unsupported assignment operator: " + assignmentExpression.Operator.ToString());
                    }
                }

                if (special)
                {
                    if (this.Emitter.Writers.Count == initCount)
                    {
                        this.Write("= ");
                    }
                    this.Write(root);

                    switch (assignmentExpression.Operator)
                    {
                    case AssignmentOperatorType.Assign:
                        break;

                    case AssignmentOperatorType.Add:
                        this.Write(JS.Funcs.Math.ADD);
                        break;

                    case AssignmentOperatorType.BitwiseAnd:
                        this.Write(isBool ? JS.Funcs.Math.AND : JS.Funcs.Math.BAND);
                        break;

                    case AssignmentOperatorType.BitwiseOr:
                        this.Write(isBool ? JS.Funcs.Math.OR : JS.Funcs.Math.BOR);
                        break;

                    case AssignmentOperatorType.Divide:
                        this.Write(JS.Funcs.Math.DIV);
                        break;

                    case AssignmentOperatorType.ExclusiveOr:
                        this.Write(JS.Funcs.Math.XOR);
                        break;

                    case AssignmentOperatorType.Modulus:
                        this.Write(JS.Funcs.Math.MOD);
                        break;

                    case AssignmentOperatorType.Multiply:
                        this.Write(JS.Funcs.Math.MUL);
                        break;

                    case AssignmentOperatorType.ShiftLeft:
                        this.Write(JS.Funcs.Math.SL);
                        break;

                    case AssignmentOperatorType.ShiftRight:
                        this.Write(isUint ? JS.Funcs.Math.SRR : JS.Funcs.Math.SR);
                        break;

                    case AssignmentOperatorType.Subtract:
                        this.Write(JS.Funcs.Math.SUB);
                        break;

                    default:
                        throw new EmitterException(assignmentExpression,
                                                   "Unsupported assignment operator: " + assignmentExpression.Operator.ToString());
                    }

                    this.WriteOpenParentheses();

                    assignmentExpression.Left.AcceptVisitor(this.Emitter);
                    this.Write(", ");
                }

                if (this.Emitter.Writers.Count == initCount && !thisAssignment && !special)
                {
                    this.Write("= ");
                }
            }
            else if (!isEvent)
            {
                this.WriteComma();
            }

            if (!special && isBool && (assignmentExpression.Operator == AssignmentOperatorType.BitwiseAnd || assignmentExpression.Operator == AssignmentOperatorType.BitwiseOr))
            {
                this.Write("!!(");
                assignmentExpression.Left.AcceptVisitor(this.Emitter);
                this.Write(assignmentExpression.Operator == AssignmentOperatorType.BitwiseAnd ? " & " : " | ");
            }

            oldValue = this.Emitter.ReplaceAwaiterByVar;
            this.Emitter.ReplaceAwaiterByVar = true;

            if (charToString == 1)
            {
                this.Write(JS.Funcs.STRING_FROMCHARCODE + "(");
            }

            if (needTempVar)
            {
                this.Write(variable);
            }
            else
            {
                var wrap = assignmentExpression.Operator != AssignmentOperatorType.Assign &&
                           this.Emitter.Writers.Count > initCount &&
                           !AssigmentExpressionHelper.CheckIsRightAssigmentExpression(assignmentExpression);

                if (wrap)
                {
                    this.WriteOpenParentheses();
                }

                assignmentExpression.Right.AcceptVisitor(this.Emitter);

                if (wrap)
                {
                    this.WriteCloseParentheses();
                }
            }

            if (!special && isBool &&
                (assignmentExpression.Operator == AssignmentOperatorType.BitwiseAnd ||
                 assignmentExpression.Operator == AssignmentOperatorType.BitwiseOr))
            {
                this.WriteCloseParentheses();
            }

            if (charToString == 1)
            {
                this.WriteCloseParentheses();
            }

            if (special)
            {
                this.WriteCloseParentheses();
            }

            if (thisAssignment)
            {
                this.Write(")." + JS.Funcs.CLONE + "(this)");
            }

            this.Emitter.ReplaceAwaiterByVar     = oldValue;
            this.Emitter.AsyncExpressionHandling = asyncExpressionHandling;

            if (this.Emitter.Writers.Count > initCount)
            {
                var writerCount = this.Emitter.Writers.Count;
                for (int i = initCount; i < writerCount; i++)
                {
                    this.PopWriter();
                }
            }

            if (delegateAssigment)
            {
                this.WriteCloseParentheses();
            }

            if (needTempVar)
            {
                this.Write(", " + variable + ")");
            }
            else if (needReturnValue)
            {
                if (!isField)
                {
                    this.Write(", ");
                    this.Emitter.IsAssignment = false;
                    assignmentExpression.Right.AcceptVisitor(this.Emitter);
                    this.Emitter.IsAssignment = oldAssigment;
                }

                this.Write(")");
            }
        }
예제 #12
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);
        }
예제 #13
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;
        }
예제 #14
0
        private static bool CheckTypeConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion, string typeName, IsType isType, bool ignoreConversionResolveResult)
        {
            if (conversion.IsUserDefined)
            {
                var m = conversion.Method;
                if (isType(m.ReturnType, block.Emitter.Resolver))
                {
                    return(false);
                }
            }

            if (expression is CastExpression && !ignoreConversionResolveResult)
            {
                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("." + JS.Funcs.Math.LIFT);
                        }
                        if (!ignoreConversionResolveResult && 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("." + JS.Funcs.Math.LIFT);
                        }
                        if (!ignoreConversionResolveResult && 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("." + JS.Funcs.Math.LIFT);
                    }
                    if (!ignoreConversionResolveResult && 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("." + JS.Funcs.Math.LIFT);
                    }
                    if (!ignoreConversionResolveResult && 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("." + JS.Funcs.Math.LIFT);
                    }
                    if (!ignoreConversionResolveResult && 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 ? 1 : 2;
                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("." + JS.Funcs.Math.LIFT);
                    }
                    if (!ignoreConversionResolveResult && 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("." + JS.Funcs.Math.LIFT);
                    }
                    if (!ignoreConversionResolveResult && 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)
                    {
                        var parameters = invocationrr.Member.Parameters;
                        if (parameters.Count <= index)
                        {
                            index = parameters.Count - 1;
                        }

                        if (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("." + JS.Funcs.Math.LIFT);
                            }
                            if (!ignoreConversionResolveResult && 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("." + JS.Funcs.Math.LIFT);
                    }
                    if (!ignoreConversionResolveResult && 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(JS.Types.System.Int64.TONUMBER);
                    if (!ignoreConversionResolveResult && 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("." + JS.Funcs.Math.LIFT);
                    }

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

            return(false);
        }
예제 #15
0
        protected virtual void EmitCastExpression(Expression expression, AstType type, string method)
        {
            var    itype = this.Emitter.BridgeTypes.ToType(type);
            bool   isCastAttr;
            string castCode = this.GetCastCode(expression, type, method, out isCastAttr);

            var enumType = itype;

            if (NullableType.IsNullable(enumType))
            {
                enumType = NullableType.GetUnderlyingType(enumType);
            }

            var castToEnum = enumType.Kind == TypeKind.Enum;

            if (castToEnum)
            {
                itype = enumType.GetDefinition().EnumUnderlyingType;
                var enumMode = Helpers.EnumEmitMode(enumType);
                if (enumMode >= 3 && enumMode < 7)
                {
                    itype = this.Emitter.Resolver.Compilation.FindType(KnownTypeCode.String);
                }
            }

            if (expression is NullReferenceExpression || (method != CS.Ops.IS && Helpers.IsIgnoreCast(type, this.Emitter)) || this.IsExternalCast(itype))
            {
                if (expression is ParenthesizedExpression)
                {
                    expression = ((ParenthesizedExpression)expression).Expression;
                }

                expression.AcceptVisitor(this.Emitter);
                return;
            }

            var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter);
            var typerr       = this.Emitter.Resolver.ResolveNode(type, this.Emitter);

            if (expressionrr.Type.Kind == TypeKind.Enum)
            {
                var enumMode = Helpers.EnumEmitMode(expressionrr.Type);
                if (enumMode >= 3 && enumMode < 7 && Helpers.IsIntegerType(itype, this.Emitter.Resolver))
                {
                    throw new EmitterException(this.CastExpression, "Enum underlying type is string and cannot be casted to number");
                }
            }

            if (method == CS.Ops.CAST && expressionrr.Type.Kind != TypeKind.Enum)
            {
                var cast_rr = this.Emitter.Resolver.ResolveNode(this.CastExpression, this.Emitter);

                if (cast_rr is ConstantResolveResult)
                {
                    var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression);
                    var value        = ((ConstantResolveResult)cast_rr).ConstantValue;

                    this.WriteCastValue(value, expectedType);
                    return;
                }
                else
                {
                    var conv_rr = cast_rr as ConversionResolveResult;
                    if (conv_rr != null && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined)
                    {
                        var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression);
                        var value        = ((ConstantResolveResult)conv_rr.Input).ConstantValue;
                        this.WriteCastValue(value, expectedType);
                        return;
                    }
                }
            }

            if (method == CS.Ops.IS && castToEnum)
            {
                this.Write(JS.Types.Bridge.IS);
                this.WriteOpenParentheses();
                expression.AcceptVisitor(this.Emitter);
                this.Write(", ");
                this.Write(BridgeTypes.ToJsName(itype, this.Emitter));
                this.Write(")");
                return;
            }

            if (expressionrr.Type.Equals(itype))
            {
                if (method == CS.Ops.IS)
                {
                    this.Write(JS.Funcs.BRIDGE_HASVALUE);
                    this.WriteOpenParentheses();
                }
                expression.AcceptVisitor(this.Emitter);
                if (method == CS.Ops.IS)
                {
                    this.Write(")");
                }

                return;
            }

            bool isResultNullable = NullableType.IsNullable(typerr.Type);

            if (castCode != null)
            {
                this.EmitInlineCast(expressionrr, expression, type, castCode, isCastAttr, method);
                return;
            }

            bool isCast = method == CS.Ops.CAST;

            if (isCast)
            {
                if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression) || ConversionBlock.IsUserDefinedConversion(this, this.CastExpression))
                {
                    expression.AcceptVisitor(this.Emitter);

                    return;
                }
            }

            var conversion = this.Emitter.Resolver.Resolver.GetConversion(expression);

            if (conversion.IsNumericConversion || conversion.IsEnumerationConversion || (isCast && conversion.IsIdentityConversion))
            {
                expression.AcceptVisitor(this.Emitter);
                return;
            }

            var  simpleType = type as SimpleType;
            bool hasValue   = false;

            if (simpleType != null && simpleType.Identifier == "dynamic")
            {
                if (method == CS.Ops.CAST || method == CS.Ops.AS)
                {
                    expression.AcceptVisitor(this.Emitter);
                    return;
                }
                else if (method == CS.Ops.IS)
                {
                    hasValue = true;
                    method   = "hasValue";
                }
            }

            bool unbox = this.Emitter.Rules.Boxing == BoxingRule.Managed && !(itype.IsReferenceType.HasValue ? itype.IsReferenceType.Value : true) && !NullableType.IsNullable(itype) && isCast && conversion.IsUnboxingConversion;

            if (unbox)
            {
                this.Write("System.Nullable.getValue(");
            }

            var typeDef = itype.Kind == TypeKind.TypeParameter ? null : this.Emitter.GetTypeDefinition(type, true);

            if (typeDef != null && method == CS.Ops.IS && itype.Kind != TypeKind.Interface && this.Emitter.Validator.IsObjectLiteral(typeDef) && this.Emitter.Validator.GetObjectCreateMode(typeDef) == 0)
            {
                throw new EmitterException(type, $"ObjectLiteral type ({itype.FullName}) with Plain mode cannot be used in 'is' operator. Please define cast logic in Cast attribute or use Constructor mode.");
            }

            this.Write(JS.NS.BRIDGE);
            this.WriteDot();
            this.Write(method);
            this.WriteOpenParentheses();

            expression.AcceptVisitor(this.Emitter);

            if (!hasValue)
            {
                this.WriteComma();
                this.EmitCastType(itype);
            }

            if (isResultNullable && method != CS.Ops.IS)
            {
                this.WriteComma();
                this.WriteScript(true);
            }

            this.WriteCloseParentheses();

            if (unbox)
            {
                this.Write(")");
            }
        }
예제 #16
0
        protected void VisitBinaryOperatorExpression()
        {
            BinaryOperatorExpression binaryOperatorExpression = this.BinaryOperatorExpression;
            var  resolveOperator       = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression, this.Emitter);
            var  expectedType          = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression);
            bool isDecimalExpected     = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver);
            bool isDecimal             = Helpers.IsDecimalType(resolveOperator.Type, this.Emitter.Resolver);
            bool isLongExpected        = Helpers.Is64Type(expectedType, this.Emitter.Resolver);
            bool isLong                = Helpers.Is64Type(resolveOperator.Type, this.Emitter.Resolver);
            OperatorResolveResult orr  = resolveOperator as OperatorResolveResult;
            var    leftResolverResult  = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Left, this.Emitter);
            var    rightResolverResult = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Right, this.Emitter);
            var    charToString        = -1;
            string variable            = null;
            bool   leftIsNull          = this.BinaryOperatorExpression.Left is NullReferenceExpression;
            bool   rightIsNull         = this.BinaryOperatorExpression.Right is NullReferenceExpression;
            bool   isUint              = resolveOperator.Type.IsKnownType(KnownTypeCode.UInt16) ||
                                         resolveOperator.Type.IsKnownType(KnownTypeCode.UInt32) ||
                                         resolveOperator.Type.IsKnownType(KnownTypeCode.UInt64);

            if ((leftIsNull || rightIsNull) && (binaryOperatorExpression.Operator == BinaryOperatorType.Equality || binaryOperatorExpression.Operator == BinaryOperatorType.InEquality))
            {
                if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality)
                {
                    this.Write("!");
                }

                this.Write("Bridge.hasValue");

                this.WriteOpenParentheses();

                if (leftIsNull)
                {
                    binaryOperatorExpression.Right.AcceptVisitor(this.Emitter);
                }
                else
                {
                    binaryOperatorExpression.Left.AcceptVisitor(this.Emitter);
                }

                this.WriteCloseParentheses();
                return;
            }

            if (orr != null && orr.Type.IsKnownType(KnownTypeCode.String))
            {
                for (int i = 0; i < orr.Operands.Count; i++)
                {
                    var crr = orr.Operands[i] as ConversionResolveResult;
                    if (crr != null && crr.Input.Type.IsKnownType(KnownTypeCode.Char))
                    {
                        charToString = i;
                    }
                }
            }

            if (resolveOperator is ConstantResolveResult)
            {
                this.WriteScript(((ConstantResolveResult)resolveOperator).ConstantValue);
                return;
            }

            if (!((expectedType.IsKnownType(KnownTypeCode.String) || resolveOperator.Type.IsKnownType(KnownTypeCode.String)) && binaryOperatorExpression.Operator == BinaryOperatorType.Add) && (Helpers.IsDecimalType(leftResolverResult.Type, this.Emitter.Resolver) || Helpers.IsDecimalType(rightResolverResult.Type, this.Emitter.Resolver)))
            {
                isDecimal         = true;
                isDecimalExpected = true;
            }

            if (isDecimal && isDecimalExpected && binaryOperatorExpression.Operator != BinaryOperatorType.NullCoalescing)
            {
                this.HandleDecimal(resolveOperator);
                return;
            }

            var isFloatResult = Helpers.IsFloatType(resolveOperator.Type, this.Emitter.Resolver);
            var leftExpected  = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left);
            var rightExpected = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right);
            var isLeftLong    = Helpers.Is64Type(leftExpected, this.Emitter.Resolver);
            var isRightLong   = Helpers.Is64Type(rightExpected, this.Emitter.Resolver);

            if (!((expectedType.IsKnownType(KnownTypeCode.String) || resolveOperator.Type.IsKnownType(KnownTypeCode.String)) && binaryOperatorExpression.Operator == BinaryOperatorType.Add) && (isLeftLong || isRightLong))
            {
                isLong         = true;
                isLongExpected = true;
            }

            if (isLong && isLongExpected && binaryOperatorExpression.Operator != BinaryOperatorType.NullCoalescing)
            {
                if (!isFloatResult || binaryOperatorExpression.Operator == BinaryOperatorType.Divide && isLeftLong)
                {
                    this.HandleLong(resolveOperator, isUint);
                    return;
                }
            }

            var delegateOperator = false;

            if (this.ResolveOperator(binaryOperatorExpression, orr))
            {
                return;
            }

            if (binaryOperatorExpression.Operator == BinaryOperatorType.Divide &&
                !(this.Emitter.IsJavaScriptOverflowMode && !ConversionBlock.InsideOverflowContext(this.Emitter, binaryOperatorExpression)) &&
                (
                    (Helpers.IsIntegerType(leftResolverResult.Type, this.Emitter.Resolver) &&
                     Helpers.IsIntegerType(rightResolverResult.Type, this.Emitter.Resolver)) ||

                    (Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left), this.Emitter.Resolver) &&
                     Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right), this.Emitter.Resolver))
                ))
            {
                this.Write("Bridge.Int.div(");
                binaryOperatorExpression.Left.AcceptVisitor(this.Emitter);
                this.Write(", ");
                binaryOperatorExpression.Right.AcceptVisitor(this.Emitter);
                this.Write(")");
                return;
            }

            if (binaryOperatorExpression.Operator == BinaryOperatorType.Add ||
                binaryOperatorExpression.Operator == BinaryOperatorType.Subtract)
            {
                var add = binaryOperatorExpression.Operator == BinaryOperatorType.Add;

                if (this.Emitter.Validator.IsDelegateOrLambda(leftResolverResult) && this.Emitter.Validator.IsDelegateOrLambda(rightResolverResult))
                {
                    delegateOperator = true;
                    this.Write(Bridge.Translator.Emitter.ROOT + "." + (add ? Bridge.Translator.Emitter.DELEGATE_COMBINE : Bridge.Translator.Emitter.DELEGATE_REMOVE));
                    this.WriteOpenParentheses();
                }
            }

            bool   nullable     = orr != null && orr.IsLiftedOperator;
            bool   isCoalescing = binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing;
            string root         = Bridge.Translator.Emitter.ROOT + ".Nullable.";
            bool   special      = nullable;
            bool   rootSpecial  = nullable;
            bool   isBool       = NullableType.IsNullable(resolveOperator.Type) ? NullableType.GetUnderlyingType(resolveOperator.Type).IsKnownType(KnownTypeCode.Boolean) : resolveOperator.Type.IsKnownType(KnownTypeCode.Boolean);
            bool   toBool       = isBool && !rootSpecial && !delegateOperator && (binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseAnd || binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseOr);

            if (rootSpecial)
            {
                this.Write(root);
            }
            else
            {
                if (isCoalescing)
                {
                    this.Write("(");
                    variable = this.GetTempVarName();
                    this.Write(variable);
                    this.Write(" = ");
                }
                else if (charToString == 0)
                {
                    this.Write("String.fromCharCode(");
                }

                if (toBool)
                {
                    this.Write("!!(");
                }

                binaryOperatorExpression.Left.AcceptVisitor(this.Emitter);

                if (isCoalescing)
                {
                    this.Write(", Bridge.hasValue(");
                    this.Write(variable);
                    this.Write(") ? ");
                    this.Write(variable);
                }
                else if (charToString == 0)
                {
                    this.Write(")");
                }
            }

            if (!delegateOperator)
            {
                if (!special)
                {
                    this.WriteSpace();
                }

                switch (binaryOperatorExpression.Operator)
                {
                case BinaryOperatorType.Add:
                    this.Write(rootSpecial ? "add" : "+");
                    break;

                case BinaryOperatorType.BitwiseAnd:
                    if (isBool)
                    {
                        this.Write(rootSpecial ? "and" : "&");
                    }
                    else
                    {
                        this.Write(rootSpecial ? "band" : "&");
                    }

                    break;

                case BinaryOperatorType.BitwiseOr:
                    if (isBool)
                    {
                        this.Write(rootSpecial ? "or" : "|");
                    }
                    else
                    {
                        this.Write(rootSpecial ? "bor" : "|");
                    }
                    break;

                case BinaryOperatorType.ConditionalAnd:
                    this.Write(rootSpecial ? "and" : "&&");
                    break;

                case BinaryOperatorType.NullCoalescing:
                    this.Write(":");
                    break;

                case BinaryOperatorType.ConditionalOr:
                    this.Write(rootSpecial ? "or" : "||");
                    break;

                case BinaryOperatorType.Divide:
                    this.Write(rootSpecial ? "div" : "/");
                    break;

                case BinaryOperatorType.Equality:
                    this.Write(rootSpecial ? "eq" : "===");
                    break;

                case BinaryOperatorType.ExclusiveOr:
                    this.Write(rootSpecial ? "xor" : "^");
                    break;

                case BinaryOperatorType.GreaterThan:
                    this.Write(rootSpecial ? "gt" : ">");
                    break;

                case BinaryOperatorType.GreaterThanOrEqual:
                    this.Write(rootSpecial ? "gte" : ">=");
                    break;

                case BinaryOperatorType.InEquality:
                    this.Write(rootSpecial ? "neq" : "!==");
                    break;

                case BinaryOperatorType.LessThan:
                    this.Write(rootSpecial ? "lt" : "<");
                    break;

                case BinaryOperatorType.LessThanOrEqual:
                    this.Write(rootSpecial ? "lte" : "<=");
                    break;

                case BinaryOperatorType.Modulus:
                    this.Write(rootSpecial ? "mod" : "%");
                    break;

                case BinaryOperatorType.Multiply:
                    this.Write(rootSpecial ? "mul" : "*");
                    break;

                case BinaryOperatorType.ShiftLeft:
                    this.Write(rootSpecial ? "sl" : "<<");
                    break;

                case BinaryOperatorType.ShiftRight:
                    if (isUint)
                    {
                        this.Write(rootSpecial ? "srr" : ">>>");
                    }
                    else
                    {
                        this.Write(rootSpecial ? "sr" : ">>");
                    }

                    break;

                case BinaryOperatorType.Subtract:
                    this.Write(rootSpecial ? "sub" : "-");
                    break;

                default:
                    throw new EmitterException(binaryOperatorExpression, "Unsupported binary operator: " + binaryOperatorExpression.Operator.ToString());
                }
            }
            else
            {
                this.WriteComma();
            }

            if (special)
            {
                this.WriteOpenParentheses();
                if (charToString == 0)
                {
                    this.Write("String.fromCharCode(");
                }

                binaryOperatorExpression.Left.AcceptVisitor(this.Emitter);

                if (charToString == 0)
                {
                    this.Write(")");
                }

                this.WriteComma();
            }
            else
            {
                this.WriteSpace();
            }

            if (charToString == 1)
            {
                this.Write("String.fromCharCode(");
            }

            binaryOperatorExpression.Right.AcceptVisitor(this.Emitter);

            if (toBool)
            {
                this.WriteCloseParentheses();
            }

            if (charToString == 1 || isCoalescing)
            {
                this.WriteCloseParentheses();
            }

            if (delegateOperator || special)
            {
                this.WriteCloseParentheses();
            }
        }
예제 #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;
        }
예제 #18
0
 private void AddOveflowFlag(KnownTypeCode typeCode, string op_name)
 {
     if ((typeCode == KnownTypeCode.Int64 || typeCode == KnownTypeCode.UInt64) && ConversionBlock.IsInCheckedContext(this.Emitter, this.BinaryOperatorExpression))
     {
         if (op_name == "add" || op_name == "sub" || op_name == "mul")
         {
             this.Write(", 1");
         }
     }
 }
예제 #19
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;
        }
예제 #20
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);
        }
예제 #21
0
 private void AddOveflowFlag(KnownTypeCode typeCode, string op_name, bool lifted)
 {
     if ((typeCode == KnownTypeCode.Int64 || typeCode == KnownTypeCode.UInt64) && ConversionBlock.IsInCheckedContext(this.Emitter, this.UnaryOperatorExpression))
     {
         if (op_name == JS.Funcs.Math.NEG || op_name == JS.Funcs.Math.DEC || op_name == JS.Funcs.Math.INC)
         {
             if (lifted)
             {
                 this.Write(", ");
             }
             this.Write("1");
         }
     }
 }
예제 #22
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);
        }
예제 #23
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 += ")";
            }
        }
예제 #24
0
 private static bool CheckDecimalConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion)
 {
     return(CheckTypeConversion(block, expression, rr, expectedType, conversion, "Bridge.Decimal", Helpers.IsDecimalType));
 }
예제 #25
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 += ")";
                    }
                }
            }
        }
예제 #26
0
 private static bool IsLongConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion)
 {
     return(IsTypeConversion(block, expression, rr, expectedType, conversion, "Bridge.Long", Helpers.IsLongType) ||
            IsTypeConversion(block, expression, rr, expectedType, conversion, "Bridge.ULong", Helpers.IsULongType));
 }
예제 #27
0
 public static void CheckInteger(ConversionBlock block, Expression expression, IType type)
 {
     NarrowingNumericOrEnumerationConversion(block, expression, NullableType.IsNullable(type) ? NullableType.GetUnderlyingType(type) : type, false, true, NullableType.IsNullable(type));
 }
예제 #28
0
        private static bool IsTypeConversion(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);
                }
            }

            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);
                        }

                        if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression)
                        {
                            return(false);
                        }
                        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);
                        }

                        if (expression is CastExpression &&
                            ((CastExpression)expression).Expression is ParenthesizedExpression)
                        {
                            return(false);
                        }
                        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);
                    }

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

                    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);
                    }

                    if (expression is CastExpression &&
                        ((CastExpression)expression).Expression is ParenthesizedExpression)
                    {
                        return(false);
                    }
                    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))
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

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

                    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);
                    }

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

                    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);
                    }

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

                    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 && isType(elementType, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver))
                {
                    if (expression.IsNull)
                    {
                        return(false);
                    }

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

                    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))
                {
                    if (expression is CastExpression &&
                        ((CastExpression)expression).Expression is ParenthesizedExpression)
                    {
                        return(false);
                    }
                    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);
                    }

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

                    return(true);
                }
            }

            return(false);
        }
예제 #29
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);
        }
예제 #30
0
        protected void VisitBinaryOperatorExpression()
        {
            BinaryOperatorExpression binaryOperatorExpression = this.BinaryOperatorExpression;

            if (this.Emitter.IsAsync && (
                    binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseAnd ||
                    binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseOr ||
                    binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalOr ||
                    binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalAnd
                    ) && this.GetAwaiters(binaryOperatorExpression).Length > 0)
            {
                if (this.Emitter.AsyncBlock.WrittenAwaitExpressions.Contains(binaryOperatorExpression))
                {
                    var index = System.Array.IndexOf(this.Emitter.AsyncBlock.AwaitExpressions, binaryOperatorExpression) + 1;
                    this.Write(JS.Vars.ASYNC_TASK_RESULT + index);
                }
                else
                {
                    var index = System.Array.IndexOf(this.Emitter.AsyncBlock.AwaitExpressions, binaryOperatorExpression) + 1;
                    this.WriteAsyncBinaryExpression(index);
                }

                return;
            }

            var  resolveOperator       = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression, this.Emitter);
            var  expectedType          = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression);
            bool isDecimalExpected     = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver);
            bool isDecimal             = Helpers.IsDecimalType(resolveOperator.Type, this.Emitter.Resolver);
            bool isLongExpected        = Helpers.Is64Type(expectedType, this.Emitter.Resolver);
            bool isLong                = Helpers.Is64Type(resolveOperator.Type, this.Emitter.Resolver);
            OperatorResolveResult orr  = resolveOperator as OperatorResolveResult;
            var    leftResolverResult  = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Left, this.Emitter);
            var    rightResolverResult = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Right, this.Emitter);
            var    charToString        = -1;
            string variable            = null;
            bool   leftIsNull          = this.BinaryOperatorExpression.Left is NullReferenceExpression;
            bool   rightIsNull         = this.BinaryOperatorExpression.Right is NullReferenceExpression;
            bool   isUint              = resolveOperator.Type.IsKnownType(KnownTypeCode.UInt16) ||
                                         resolveOperator.Type.IsKnownType(KnownTypeCode.UInt32) ||
                                         resolveOperator.Type.IsKnownType(KnownTypeCode.UInt64);

            var isFloatResult    = Helpers.IsFloatType(resolveOperator.Type, this.Emitter.Resolver);
            var leftExpected     = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left);
            var rightExpected    = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right);
            var strictNullChecks = this.Emitter.AssemblyInfo.StrictNullChecks;

            if (orr != null && orr.Type.IsKnownType(KnownTypeCode.String))
            {
                for (int i = 0; i < orr.Operands.Count; i++)
                {
                    var crr = orr.Operands[i] as ConversionResolveResult;
                    if (crr != null && crr.Input.Type.IsKnownType(KnownTypeCode.Char))
                    {
                        charToString = i;
                    }
                }
            }

            if (resolveOperator is ConstantResolveResult)
            {
                this.WriteScript(((ConstantResolveResult)resolveOperator).ConstantValue);
                return;
            }

            var resultIsString   = expectedType.IsKnownType(KnownTypeCode.String) || resolveOperator.Type.IsKnownType(KnownTypeCode.String);
            var isStringConcat   = resultIsString && binaryOperatorExpression.Operator == BinaryOperatorType.Add;
            var toStringForLeft  = false;
            var toStringForRight = false;

            var  parentBinary   = binaryOperatorExpression.Parent as BinaryOperatorExpression;
            bool parentIsString = resultIsString && parentBinary != null && parentBinary.Operator == BinaryOperatorType.Add;

            if (parentIsString)
            {
                var parentResolveOperator = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Parent, this.Emitter) as OperatorResolveResult;

                if (parentResolveOperator != null && parentResolveOperator.UserDefinedOperatorMethod != null || BinaryOperatorBlock.IsOperatorSimple(parentBinary, this.Emitter))
                {
                    parentIsString = false;
                }
            }

            bool isSimpleConcat = isStringConcat && BinaryOperatorBlock.IsOperatorSimple(binaryOperatorExpression, this.Emitter);

            if (charToString == -1 && isStringConcat && !leftResolverResult.Type.IsKnownType(KnownTypeCode.String))
            {
                toStringForLeft = true;
            }

            if (charToString == -1 && isStringConcat && !rightResolverResult.Type.IsKnownType(KnownTypeCode.String))
            {
                toStringForRight = true;
            }

            if (!isStringConcat && (Helpers.IsDecimalType(leftResolverResult.Type, this.Emitter.Resolver) || Helpers.IsDecimalType(rightResolverResult.Type, this.Emitter.Resolver)))
            {
                isDecimal         = true;
                isDecimalExpected = true;
            }

            if (isDecimal && isDecimalExpected && binaryOperatorExpression.Operator != BinaryOperatorType.NullCoalescing)
            {
                this.HandleDecimal(resolveOperator);
                return;
            }

            var isLeftLong  = Helpers.Is64Type(leftExpected, this.Emitter.Resolver);
            var isRightLong = Helpers.Is64Type(rightExpected, this.Emitter.Resolver);

            if (!isLeftLong && !isRightLong)
            {
                if (leftExpected.Kind == TypeKind.Enum && Helpers.Is64Type(leftExpected.GetDefinition().EnumUnderlyingType, this.Emitter.Resolver))
                {
                    isLeftLong = true;
                }

                if (rightExpected.Kind == TypeKind.Enum && Helpers.Is64Type(rightExpected.GetDefinition().EnumUnderlyingType, this.Emitter.Resolver))
                {
                    isRightLong = true;
                }
            }

            if (!(resultIsString && binaryOperatorExpression.Operator == BinaryOperatorType.Add) && (isLeftLong || isRightLong))
            {
                isLong         = true;
                isLongExpected = true;
            }

            if (isLong && isLongExpected && binaryOperatorExpression.Operator != BinaryOperatorType.NullCoalescing)
            {
                if (!isFloatResult || binaryOperatorExpression.Operator == BinaryOperatorType.Divide && isLeftLong)
                {
                    this.HandleLong(resolveOperator, isUint);
                    return;
                }
            }

            var delegateOperator = false;

            if (this.ResolveOperator(binaryOperatorExpression, orr))
            {
                return;
            }

            if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality || binaryOperatorExpression.Operator == BinaryOperatorType.InEquality)
            {
                if (leftIsNull || rightIsNull)
                {
                    this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult);

                    if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality)
                    {
                        this.Write(strictNullChecks ? " === " : " == ");
                    }
                    else
                    {
                        this.Write(strictNullChecks ? " !== " : " != ");
                    }

                    this.WritePart(binaryOperatorExpression.Right, toStringForRight, rightResolverResult);
                    return;
                }
            }

            var insideOverflowContext = ConversionBlock.InsideOverflowContext(this.Emitter, binaryOperatorExpression);

            if (binaryOperatorExpression.Operator == BinaryOperatorType.Divide && this.Emitter.Rules.Integer == IntegerRule.Managed &&
                !(this.Emitter.IsJavaScriptOverflowMode && !insideOverflowContext) &&
                (
                    (Helpers.IsIntegerType(leftResolverResult.Type, this.Emitter.Resolver) &&
                     Helpers.IsIntegerType(rightResolverResult.Type, this.Emitter.Resolver)) ||

                    (Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left), this.Emitter.Resolver) &&
                     Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right), this.Emitter.Resolver))
                ))
            {
                this.Write(JS.Types.BRIDGE_INT + "." + JS.Funcs.Math.DIV + "(");
                this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult);
                this.Write(", ");
                this.WritePart(binaryOperatorExpression.Right, toStringForRight, rightResolverResult);
                this.Write(")");
                return;
            }

            if (binaryOperatorExpression.Operator == BinaryOperatorType.Multiply && this.Emitter.Rules.Integer == IntegerRule.Managed &&
                !(this.Emitter.IsJavaScriptOverflowMode && !insideOverflowContext) &&
                (
                    (Helpers.IsInteger32Type(leftResolverResult.Type, this.Emitter.Resolver) &&
                     Helpers.IsInteger32Type(rightResolverResult.Type, this.Emitter.Resolver) &&
                     Helpers.IsInteger32Type(resolveOperator.Type, this.Emitter.Resolver)) ||

                    (Helpers.IsInteger32Type(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left), this.Emitter.Resolver) &&
                     Helpers.IsInteger32Type(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right), this.Emitter.Resolver) &&
                     Helpers.IsInteger32Type(resolveOperator.Type, this.Emitter.Resolver))
                ))
            {
                isUint = NullableType.GetUnderlyingType(resolveOperator.Type).IsKnownType(KnownTypeCode.UInt32);
                this.Write(JS.Types.BRIDGE_INT + "." + (isUint ? JS.Funcs.Math.UMUL : JS.Funcs.Math.MUL) + "(");
                this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult);
                this.Write(", ");
                this.WritePart(binaryOperatorExpression.Right, toStringForRight, rightResolverResult);

                if (ConversionBlock.IsInCheckedContext(this.Emitter, this.BinaryOperatorExpression))
                {
                    this.Write(", 1");
                }

                this.Write(")");
                return;
            }

            if (binaryOperatorExpression.Operator == BinaryOperatorType.Add ||
                binaryOperatorExpression.Operator == BinaryOperatorType.Subtract)
            {
                var add = binaryOperatorExpression.Operator == BinaryOperatorType.Add;

                if (expectedType.Kind == TypeKind.Delegate || this.Emitter.Validator.IsDelegateOrLambda(leftResolverResult) && this.Emitter.Validator.IsDelegateOrLambda(rightResolverResult))
                {
                    delegateOperator = true;
                    this.Write(add ? JS.Funcs.BRIDGE_COMBINE : JS.Funcs.BRIDGE_REMOVE);
                    this.WriteOpenParentheses();
                }
            }

            this.NullStringCheck = isStringConcat && !parentIsString && isSimpleConcat;
            if (isStringConcat && !parentIsString && !isSimpleConcat)
            {
                this.Write(JS.Types.System.String.CONCAT);
                this.WriteOpenParentheses();
            }

            bool nullable     = orr != null && orr.IsLiftedOperator;
            bool isCoalescing = (this.Emitter.AssemblyInfo.StrictNullChecks ||
                                 NullableType.IsNullable(leftResolverResult.Type) ||
                                 leftResolverResult.Type.IsKnownType(KnownTypeCode.String) ||
                                 leftResolverResult.Type.IsKnownType(KnownTypeCode.Object)
                                 ) && binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing;
            string root        = JS.Types.SYSTEM_NULLABLE + ".";
            bool   special     = nullable;
            bool   rootSpecial = nullable;
            bool   isBool      = NullableType.IsNullable(resolveOperator.Type) ? NullableType.GetUnderlyingType(resolveOperator.Type).IsKnownType(KnownTypeCode.Boolean) : resolveOperator.Type.IsKnownType(KnownTypeCode.Boolean);
            bool   toBool      = isBool && !rootSpecial && !delegateOperator && (binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseAnd || binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseOr);
            bool   isRefEquals = !isCoalescing && !strictNullChecks &&
                                 (binaryOperatorExpression.Operator == BinaryOperatorType.InEquality || binaryOperatorExpression.Operator == BinaryOperatorType.Equality) &&
                                 leftExpected.IsReferenceType.HasValue && leftExpected.IsReferenceType.Value &&
                                 rightExpected.IsReferenceType.HasValue && rightExpected.IsReferenceType.Value;

            if (rootSpecial)
            {
                this.Write(root);
            }
            else if (!isRefEquals)
            {
                if (isCoalescing)
                {
                    this.Write("(");
                    variable = this.GetTempVarName();
                    this.Write(variable);
                    this.Write(" = ");
                }
                else if (charToString == 0)
                {
                    this.Write(JS.Funcs.STRING_FROMCHARCODE + "(");
                }

                if (toBool)
                {
                    this.Write("!!(");
                }

                this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult, isCoalescing);

                if (isCoalescing)
                {
                    this.Write(", ");
                    this.Write(variable);

                    this.Write(strictNullChecks ? " !== null" : " != null");

                    this.Write(" ? ");

                    ConversionBlock.expressionMap.Add(binaryOperatorExpression.Left, variable);
                    //this.Write(variable);
                    binaryOperatorExpression.Left.AcceptVisitor(this.Emitter);
                    ConversionBlock.expressionMap.Remove(binaryOperatorExpression.Left);
                }
                else if (charToString == 0)
                {
                    this.Write(")");
                }
            }

            if (isRefEquals)
            {
                if (binaryOperatorExpression.Operator == BinaryOperatorType.InEquality)
                {
                    this.Write("!");
                }
                this.Write(JS.Funcs.BRIDGE_REFERENCEEQUALS);
                special = true;
            }

            if (!delegateOperator && (!isStringConcat || isSimpleConcat))
            {
                if (!special)
                {
                    this.WriteSpace();
                }

                switch (binaryOperatorExpression.Operator)
                {
                case BinaryOperatorType.Add:
                    this.Write(rootSpecial ? JS.Funcs.Math.ADD : "+");
                    break;

                case BinaryOperatorType.BitwiseAnd:
                    if (isBool)
                    {
                        this.Write(rootSpecial ? JS.Funcs.Math.AND : "&");
                    }
                    else
                    {
                        this.Write(rootSpecial ? JS.Funcs.Math.BAND : "&");
                    }

                    break;

                case BinaryOperatorType.BitwiseOr:
                    if (isBool)
                    {
                        this.Write(rootSpecial ? JS.Funcs.Math.OR : "|");
                    }
                    else
                    {
                        this.Write(rootSpecial ? JS.Funcs.Math.BOR : "|");
                    }
                    break;

                case BinaryOperatorType.ConditionalAnd:
                    this.Write(rootSpecial ? JS.Funcs.Math.AND : "&&");
                    break;

                case BinaryOperatorType.NullCoalescing:
                    this.Write(isCoalescing ? ":" : "||");
                    break;

                case BinaryOperatorType.ConditionalOr:
                    this.Write(rootSpecial ? JS.Funcs.Math.OR : "||");
                    break;

                case BinaryOperatorType.Divide:
                    this.Write(rootSpecial ? JS.Funcs.Math.DIV : "/");
                    break;

                case BinaryOperatorType.Equality:
                    if (!isRefEquals)
                    {
                        this.Write(rootSpecial ? "eq" : "===");
                    }

                    break;

                case BinaryOperatorType.ExclusiveOr:
                    this.Write(rootSpecial ? JS.Funcs.Math.XOR : "^");
                    break;

                case BinaryOperatorType.GreaterThan:
                    this.Write(rootSpecial ? JS.Funcs.Math.GT : ">");
                    break;

                case BinaryOperatorType.GreaterThanOrEqual:
                    this.Write(rootSpecial ? JS.Funcs.Math.GTE : ">=");
                    break;

                case BinaryOperatorType.InEquality:
                    if (!isRefEquals)
                    {
                        this.Write(rootSpecial ? "neq" : "!==");
                    }
                    break;

                case BinaryOperatorType.LessThan:
                    this.Write(rootSpecial ? JS.Funcs.Math.LT : "<");
                    break;

                case BinaryOperatorType.LessThanOrEqual:
                    this.Write(rootSpecial ? JS.Funcs.Math.LTE : "<=");
                    break;

                case BinaryOperatorType.Modulus:
                    this.Write(rootSpecial ? JS.Funcs.Math.MOD : "%");
                    break;

                case BinaryOperatorType.Multiply:
                    this.Write(rootSpecial ? JS.Funcs.Math.MUL : "*");
                    break;

                case BinaryOperatorType.ShiftLeft:
                    this.Write(rootSpecial ? JS.Funcs.Math.SL : "<<");
                    break;

                case BinaryOperatorType.ShiftRight:
                    if (isUint)
                    {
                        this.Write(rootSpecial ? JS.Funcs.Math.SRR : ">>>");
                    }
                    else
                    {
                        this.Write(rootSpecial ? JS.Funcs.Math.SR : ">>");
                    }

                    break;

                case BinaryOperatorType.Subtract:
                    this.Write(rootSpecial ? JS.Funcs.Math.SUB : "-");
                    break;

                default:
                    throw new EmitterException(binaryOperatorExpression, "Unsupported binary operator: " + binaryOperatorExpression.Operator.ToString());
                }
            }
            else
            {
                this.WriteComma();
            }

            if (special)
            {
                this.WriteOpenParentheses();
                if (charToString == 0)
                {
                    this.Write(JS.Funcs.STRING_FROMCHARCODE + "(");
                }

                this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult);

                if (charToString == 0)
                {
                    this.Write(")");
                }

                this.WriteComma();
            }
            else if (!delegateOperator && (!isStringConcat || isSimpleConcat))
            {
                this.WriteSpace();
            }

            if (charToString == 1)
            {
                this.Write(JS.Funcs.STRING_FROMCHARCODE + "(");
            }

            this.WritePart(binaryOperatorExpression.Right, toStringForRight, rightResolverResult);

            if (toBool)
            {
                this.WriteCloseParentheses();
            }

            if (charToString == 1 || isCoalescing)
            {
                this.WriteCloseParentheses();
            }

            if (delegateOperator || special || isStringConcat && !parentIsString && !isSimpleConcat)
            {
                this.WriteCloseParentheses();
            }
        }
예제 #31
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);
        }
예제 #32
0
 private void AddOveflowFlag(KnownTypeCode typeCode, string op_name)
 {
     if ((typeCode == KnownTypeCode.Int64 || typeCode == KnownTypeCode.UInt64) && ConversionBlock.IsInCheckedContext(this.Emitter, this.BinaryOperatorExpression))
     {
         if (op_name == JS.Funcs.Math.ADD || op_name == JS.Funcs.Math.SUB || op_name == JS.Funcs.Math.MUL)
         {
             this.Write(", 1");
         }
     }
 }
예제 #33
0
파일: CastBlock.cs 프로젝트: idannik/Bridge
        protected virtual void EmitCastExpression(Expression expression, AstType type, string method)
        {
            var    itype = this.Emitter.BridgeTypes.ToType(type);
            bool   isCastAttr;
            string castCode = this.GetCastCode(expression, type, out isCastAttr);

            if (itype != null && castCode == null && method != CS.Ops.CAST && itype.GetDefinition() != null && this.Emitter.Validator.IsObjectLiteral(itype.GetDefinition()))
            {
                throw new EmitterException(expression, "The type " + itype.FullName + " cannot be used in cast operation because there is no way to check its type");
            }

            var enumType = itype;

            if (NullableType.IsNullable(enumType))
            {
                enumType = NullableType.GetUnderlyingType(enumType);
            }

            var castToEnum = enumType.Kind == TypeKind.Enum;

            if (castToEnum)
            {
                itype = enumType.GetDefinition().EnumUnderlyingType;
                var enumMode = this.Emitter.Validator.EnumEmitMode(enumType);
                if (enumMode >= 3 && enumMode < 7)
                {
                    itype = this.Emitter.Resolver.Compilation.FindType(KnownTypeCode.String);
                }
            }

            if (expression is NullReferenceExpression || (method != CS.Ops.IS && Helpers.IsIgnoreCast(type, this.Emitter)))
            {
                if (expression is ParenthesizedExpression)
                {
                    expression = ((ParenthesizedExpression)expression).Expression;
                }

                expression.AcceptVisitor(this.Emitter);
                return;
            }

            if (method == CS.Ops.CAST)
            {
                var cast_rr = this.Emitter.Resolver.ResolveNode(this.CastExpression, this.Emitter);

                if (cast_rr is ConstantResolveResult)
                {
                    var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression);
                    var value        = ((ConstantResolveResult)cast_rr).ConstantValue;

                    this.WriteCastValue(value, expectedType);
                    return;
                }
                else
                {
                    var conv_rr = cast_rr as ConversionResolveResult;
                    if (conv_rr != null && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined)
                    {
                        var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression);
                        var value        = ((ConstantResolveResult)conv_rr.Input).ConstantValue;
                        this.WriteCastValue(value, expectedType);
                        return;
                    }
                }
            }

            if (method == CS.Ops.IS && castToEnum)
            {
                this.Write("Bridge.is(");
                expression.AcceptVisitor(this.Emitter);
                this.Write(", ");
                this.Write(BridgeTypes.ToJsName(itype, this.Emitter));
                this.Write(")");
                return;
            }

            var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter);
            var typerr       = this.Emitter.Resolver.ResolveNode(type, this.Emitter);

            if (expressionrr.Type.Equals(itype))
            {
                if (method == CS.Ops.IS)
                {
                    this.Write(JS.Funcs.BRIDGE_HASVALUE);
                    this.WriteOpenParentheses();
                }
                expression.AcceptVisitor(this.Emitter);
                if (method == CS.Ops.IS)
                {
                    this.Write(")");
                }

                return;
            }

            bool isResultNullable = NullableType.IsNullable(typerr.Type);

            if (castCode != null)
            {
                this.EmitInlineCast(expressionrr, expression, type, castCode, isCastAttr, method);
                return;
            }

            bool isCast = method == CS.Ops.CAST;

            if (isCast)
            {
                if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression) || ConversionBlock.IsUserDefinedConversion(this, this.CastExpression))
                {
                    expression.AcceptVisitor(this.Emitter);

                    return;
                }
            }

            var conversion = this.Emitter.Resolver.Resolver.GetConversion(expression);

            if (conversion.IsNumericConversion || conversion.IsEnumerationConversion || (isCast && conversion.IsIdentityConversion))
            {
                expression.AcceptVisitor(this.Emitter);
                return;
            }

            var  simpleType = type as SimpleType;
            bool hasValue   = false;

            if (simpleType != null && simpleType.Identifier == "dynamic")
            {
                if (method == CS.Ops.CAST || method == CS.Ops.AS)
                {
                    expression.AcceptVisitor(this.Emitter);
                    return;
                }
                else if (method == CS.Ops.IS)
                {
                    hasValue = true;
                    method   = "hasValue";
                }
            }

            bool unbox = !(itype.IsReferenceType.HasValue ? itype.IsReferenceType.Value : true) && !NullableType.IsNullable(itype) && isCast && conversion.IsUnboxingConversion;

            if (unbox)
            {
                this.Write("System.Nullable.getValue(");
            }

            this.Write(JS.NS.BRIDGE);
            this.WriteDot();
            this.Write(method);
            this.WriteOpenParentheses();

            expression.AcceptVisitor(this.Emitter);

            if (!hasValue)
            {
                this.WriteComma();
                this.EmitCastType(itype);
            }

            if (isResultNullable && method != CS.Ops.IS)
            {
                this.WriteComma();
                this.WriteScript(true);
            }

            this.WriteCloseParentheses();

            if (unbox)
            {
                this.Write(")");
            }
        }
예제 #34
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;
        }