Exemplo n.º 1
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");
         }
     }
 }
Exemplo n.º 2
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");
         }
     }
 }
Exemplo n.º 3
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");
         }
     }
 }
Exemplo n.º 4
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();
            }
        }
Exemplo n.º 5
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);

            var rrType = rr.Type;

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

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

            if (!isLong && rr.Type.Kind == TypeKind.Enum && Helpers.Is64Type(rr.Type.GetDefinition().EnumUnderlyingType, this.Emitter.Resolver))
            {
                isLong = true;
            }

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

            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.Rules.Integer == IntegerRule.Managed &&
                !(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;
                this.AcceptLeftExpression(assignmentExpression.Left, memberTargetrr);

                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.Multiply && this.Emitter.Rules.Integer == IntegerRule.Managed &&
                !(this.Emitter.IsJavaScriptOverflowMode && !ConversionBlock.InsideOverflowContext(this.Emitter, assignmentExpression)) &&
                !isLong && !isLongExpected &&
                (
                    (Helpers.IsInteger32Type(leftResolverResult.Type, this.Emitter.Resolver) &&
                     Helpers.IsInteger32Type(rightResolverResult.Type, this.Emitter.Resolver) &&
                     Helpers.IsInteger32Type(rr.Type, this.Emitter.Resolver)) ||

                    (Helpers.IsInteger32Type(this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Left), this.Emitter.Resolver) &&
                     Helpers.IsInteger32Type(this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Right), this.Emitter.Resolver) &&
                     Helpers.IsInteger32Type(rr.Type, this.Emitter.Resolver))
                ))
            {
                this.Emitter.IsAssignment   = true;
                this.Emitter.AssignmentType = AssignmentOperatorType.Assign;
                var oldValue1 = this.Emitter.ReplaceAwaiterByVar;
                this.Emitter.ReplaceAwaiterByVar = true;
                this.AcceptLeftExpression(assignmentExpression.Left, memberTargetrr);

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

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

                isUint = NullableType.GetUnderlyingType(rr.Type).IsKnownType(KnownTypeCode.UInt32);
                this.Write(JS.Types.BRIDGE_INT + "." + (isUint ? JS.Funcs.Math.UMUL : JS.Funcs.Math.MUL) + "(");
                assignmentExpression.Left.AcceptVisitor(this.Emitter);
                this.Write(", ");
                oldValue1 = this.Emitter.ReplaceAwaiterByVar;
                this.Emitter.ReplaceAwaiterByVar = true;

                assignmentExpression.Right.AcceptVisitor(this.Emitter);

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

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

            bool templateDelegateAssigment = false;

            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;
                        this.Emitter.IsAssignment   = true;
                        this.Emitter.AssignmentType = assignmentExpression.Operator;
                        templateDelegateAssigment   = !string.IsNullOrWhiteSpace(this.Emitter.GetInline(leftMemberResolveResult.Member));
                        this.Emitter.IsAssignment   = false;
                    }

                    if (!isEvent)
                    {
                        this.Emitter.IsAssignment   = true;
                        this.Emitter.AssignmentType = AssignmentOperatorType.Assign;
                        this.AcceptLeftExpression(assignmentExpression.Left, memberTargetrr);
                        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;
                }

                this.AcceptLeftExpression(assignmentExpression.Left, memberTargetrr);

                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:
                        if (!isBool)
                        {
                            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 || assignmentExpression.Operator == AssignmentOperatorType.ExclusiveOr))
            {
                if (assignmentExpression.Operator != AssignmentOperatorType.ExclusiveOr)
                {
                    this.Write("!!(");
                }

                assignmentExpression.Left.AcceptVisitor(this.Emitter);

                string op = null;
                switch (assignmentExpression.Operator)
                {
                case AssignmentOperatorType.BitwiseAnd:
                    op = " & ";
                    break;

                case AssignmentOperatorType.BitwiseOr:
                    op = " | ";
                    break;

                case AssignmentOperatorType.ExclusiveOr:
                    op = " != ";
                    break;
                }
                this.Write(op);
            }

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

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

            if (needTempVar)
            {
                int pos = this.Emitter.Output.Length;
                this.Write(variable);
                Helpers.CheckValueTypeClone(rr, assignmentExpression.Right, this, pos);
            }
            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 && !templateDelegateAssigment)
            {
                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(")");
            }
        }