예제 #1
0
        public override void OnBinaryExpression(BinaryExpression node)
        {
            if (node.Operator == BinaryOperatorType.Assign)
            {
                OnAssignment(node);
                return;
            }
            if (node.Operator == BinaryOperatorType.TypeTest)
            {
                OnIsaOperator(node);
                return;
            }

            BoundSpillSequenceBuilder builder = null;
            var        right = VisitExpression(ref builder, node.Right);
            Expression left;

            if (builder == null)
            {
                left = VisitExpression(ref builder, node.Left);
            }
            else
            {
                var leftBuilder = new BoundSpillSequenceBuilder();
                left = VisitExpression(ref leftBuilder, node.Left);
                left = Spill(leftBuilder, left);
                if (node.Operator == BinaryOperatorType.Or || node.Operator == BinaryOperatorType.And)
                {
                    var tmp = _F.DeclareTempLocal(_currentMethod, node.ExpressionType);
                    tmp.Local["SynthesizedKind"] = AWAIT_SPILL_MARKER;
                    leftBuilder.AddLocal(tmp);
                    leftBuilder.AddStatement(new ExpressionStatement(_F.CreateAssignment(_F.CreateLocalReference(tmp), left)));
                    var trueBlock = new Block();
                    trueBlock.Add(UpdateExpression(builder, _F.CreateAssignment(_F.CreateLocalReference(tmp), right)));
                    leftBuilder.AddStatement(
                        new IfStatement(left.LexicalInfo,
                                        node.Operator == BinaryOperatorType.And ?
                                        _F.CreateLocalReference(tmp) :
                                        (Expression)_F.CreateNotExpression(_F.CreateLocalReference(tmp)),
                                        trueBlock,
                                        null));

                    ReplaceCurrentNode(UpdateExpression(leftBuilder, _F.CreateLocalReference(tmp)));
                    return;
                }
                // if the right-hand-side has await, spill the left
                leftBuilder.Include(builder);
                builder = leftBuilder;
            }

            node.Left  = left;
            node.Right = right;
            ReplaceCurrentNode(UpdateExpression(builder, node));
        }