public sealed override BoundNode VisitBinaryOperator(BoundBinaryOperator node) { BoundExpression child = node.Left; if (child.Kind != BoundKind.BinaryOperator) { return(base.VisitBinaryOperator(node)); } var stack = ArrayBuilder <BoundBinaryOperator> .GetInstance(); stack.Push(node); BoundBinaryOperator binary = (BoundBinaryOperator)child; while (true) { stack.Push(binary); child = binary.Left; if (child.Kind != BoundKind.BinaryOperator) { break; } binary = (BoundBinaryOperator)child; } var left = (BoundExpression)this.Visit(child); do { binary = stack.Pop(); var right = (BoundExpression)this.Visit(binary.Right); var type = this.VisitType(binary.Type); left = binary.Update(binary.OperatorKind, binary.ConstantValueOpt, binary.MethodOpt, binary.ResultKind, left, right, type); }while (stack.Count > 0); Debug.Assert((object)binary == node); stack.Free(); return(left); }
public override BoundNode VisitBinaryOperator(BoundBinaryOperator node) { BoundSpillSequenceBuilder builder = null; var right = VisitExpression(ref builder, node.Right); BoundExpression 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.OperatorKind == BinaryOperatorKind.LogicalBoolOr || node.OperatorKind == BinaryOperatorKind.LogicalBoolAnd) { var tmp = _F.SynthesizedLocal(node.Type, kind: SynthesizedLocalKind.Spill, syntax: _F.Syntax); leftBuilder.AddLocal(tmp); leftBuilder.AddStatement(_F.Assignment(_F.Local(tmp), left)); leftBuilder.AddStatement(_F.If( node.OperatorKind == BinaryOperatorKind.LogicalBoolAnd ? _F.Local(tmp) : _F.Not(_F.Local(tmp)), UpdateStatement(builder, _F.Assignment(_F.Local(tmp), right)))); return(UpdateExpression(leftBuilder, _F.Local(tmp))); } else { // if the right-hand-side has await, spill the left leftBuilder.Include(builder); builder = leftBuilder; } } return(UpdateExpression(builder, node.Update(node.OperatorKind, node.ConstantValue, node.MethodOpt, node.ResultKind, left, right, node.Type))); }