private void LowerWhenClause(BoundWhenDecisionDagNode whenClause) { // This node is used even when there is no when clause, to record bindings. In the case that there // is no when clause, whenClause.WhenExpression and whenClause.WhenFalse are null, and the syntax for this // node is the case clause. // We need to assign the pattern variables in the code where they are in scope, so we produce a branch // to the section where they are in scope and evaluate the when clause there. var whenTrue = (BoundLeafDecisionDagNode)whenClause.WhenTrue; LabelSymbol labelToSectionScope = GetDagNodeLabel(whenClause); // We need the section syntax to get the section builder from the map. Unfortunately this is a bit awkward SyntaxNode sectionSyntax = whenClause.Syntax is SwitchLabelSyntax l ? l.Parent : whenClause.Syntax; bool foundSectionBuilder = _switchArms.TryGetValue(sectionSyntax, out ArrayBuilder <BoundStatement> sectionBuilder); Debug.Assert(foundSectionBuilder); sectionBuilder.Add(_factory.Label(labelToSectionScope)); foreach (BoundPatternBinding binding in whenClause.Bindings) { BoundExpression left = _localRewriter.VisitExpression(binding.VariableAccess); // Since a switch does not add variables to the enclosing scope, the pattern variables // are locals even in a script and rewriting them should have no effect. Debug.Assert(left.Kind == BoundKind.Local && left == binding.VariableAccess); BoundExpression right = _tempAllocator.GetTemp(binding.TempContainingValue); if (left != right) { sectionBuilder.Add(_factory.Assignment(left, right)); } } var whenFalse = whenClause.WhenFalse; var trueLabel = GetDagNodeLabel(whenTrue); if (whenClause.WhenExpression != null && whenClause.WhenExpression.ConstantValue != ConstantValue.True) { _factory.Syntax = whenClause.Syntax; BoundStatement conditionalGoto = _factory.ConditionalGoto(_localRewriter.VisitExpression(whenClause.WhenExpression), trueLabel, jumpIfTrue: true); // Only add instrumentation (such as a sequence point) if the node is not compiler-generated. if (IsSwitchStatement && !whenClause.WhenExpression.WasCompilerGenerated && _localRewriter.Instrument) { conditionalGoto = _localRewriter._instrumenter.InstrumentSwitchWhenClauseConditionalGotoBody(whenClause.WhenExpression, conditionalGoto); } sectionBuilder.Add(conditionalGoto); Debug.Assert(whenFalse != null); // We hide the jump back into the decision dag, as it is not logically part of the when clause BoundStatement jump = _factory.Goto(GetDagNodeLabel(whenFalse)); sectionBuilder.Add(IsSwitchStatement ? _factory.HiddenSequencePoint(jump) : jump); } else { Debug.Assert(whenFalse == null); sectionBuilder.Add(_factory.Goto(trueLabel)); } }
private void LowerWhenClause(BoundWhenDecisionDagNode whenClause) { // This node is used even when there is no when clause, to record bindings. In the case that there // is no when clause, whenClause.WhenExpression and whenClause.WhenFalse are null, and the syntax for this // node is the case clause. // We need to assign the pattern variables in the code where they are in scope, so we produce a branch // to the section where they are in scope and evaluate the when clause there. var whenTrue = (BoundLeafDecisionDagNode)whenClause.WhenTrue; LabelSymbol labelToSectionScope = GetDagNodeLabel(whenClause); // We need the section syntax to get the section builder from the map. Unfortunately this is a bit awkward SyntaxNode?sectionSyntax = whenClause.Syntax is SwitchLabelSyntax l ? l.Parent : whenClause.Syntax; Debug.Assert(sectionSyntax is { });