/// <summary> /// Visit a boolean condition expression, where we will be wanting AssignedWhenTrue and /// AssignedWhenFalse. /// </summary> /// <param name="node"></param> protected void VisitCondition(BoundExpression node) { Debug.Assert(!this.state.Assigned.IsNull); Visit(node); // We implement the foundational rules missing from the language specification: // v is "definitely assigned when true" after a constant expression whose value is false. // v is "definitely assigned when false" after a constant expression whose value is true. // These rules are to be added to the language specification. // It was the lack of these foundational rules that led to the invention of the concept // of "unreachable expression" in the native compiler. if (IsConstantTrue(node)) { state.Merge(); this.state = new FlowAnalysisLocalState(this.state.Reachable, this.state.Assigned, BitArray.AllSet(nextVariableSlot)); } else if (IsConstantFalse(node)) { state.Merge(); this.state = new FlowAnalysisLocalState(this.state.Reachable, BitArray.AllSet(nextVariableSlot), this.state.Assigned); } else { state.Split(); } }
/// <summary> /// Create a new "unreachable" state, in which every variable slot (up to nextVariableSlot) /// is treated as assigned. /// </summary> /// <param name="nextVariableSlot"></param> /// <returns></returns> public static FlowAnalysisLocalState UnreachableState(int nextVariableSlot) { FlowAnalysisLocalState result; result.Reachable = false; result.Assigned = BitArray.AllSet(nextVariableSlot); result.AssignedWhenTrue = result.AssignedWhenFalse = BitArray.Null; return(result); }
public override object VisitForStatement(BoundForStatement node, object arg) { VisitStatement(node.Initializer); LoopHead(node); bool isTrue; bool isFalse; if (node.Condition != null) { isFalse = IsConstantFalse(node.Condition); isTrue = IsConstantTrue(node.Condition); VisitCondition(node.Condition); } else { isTrue = true; isFalse = false; this.state = new FlowAnalysisLocalState(this.state.Reachable, this.state.Assigned, BitArray.AllSet(nextVariableSlot)); } var bodyState = new FlowAnalysisLocalState(this.state.Reachable && !isFalse, this.state.AssignedWhenTrue); var breakState = new FlowAnalysisLocalState(this.state.Reachable && !isTrue, this.state.AssignedWhenFalse); var oldPendingBranches = this.pendingBranches; this.pendingBranches = ArrayBuilder <PendingBranch> .GetInstance(); this.state = bodyState; VisitStatement(node.Body); ResolveContinues(node.ContinueLabel); VisitStatement(node.Increment); LoopTail(node); ResolveBreaks(oldPendingBranches, breakState, node.BreakLabel); return(null); }