/// <summary> /// /// </summary> /// <param name="rootState"></param> /// <param name="errDelegate"></param> to report err back to GUI /// <returns></returns> internal static IEnumerable <ProofState> GenerateSolution(ProofState rootState, ErrorReporterDelegate errDelegate) { var stack = new Stack <IEnumerator <ProofState> >(); ProofState lastSucc = null; // the last verified state, for recovering over-backtracking var discarded = new List <Tuple <ProofState, VerifyResult> >(); // failed ps and its verified status List <ProofState> proofState = new List <ProofState> () { rootState }; var rootBranches = rootState.EvalStep(); if (rootBranches == null) { yield break; } stack.Push(rootBranches.GetEnumerator()); IEnumerator <ProofState> enumerator = null; List <int> backtrackList = null; while (stack.Count > 0) { bool wasNull = false; if (enumerator != null) { try { if (enumerator.Current == null) { wasNull = true; } } catch { wasNull = true; } } if (enumerator == null || !enumerator.MoveNext()) { // check if current is valid, and the enumerator is empty when current is invalid and MoveNext is null if (enumerator != null && wasNull) { //Console.WriteLine("Null eval result is detected !"); foreach (var state in proofState) { discarded.Add(new Tuple <ProofState, VerifyResult>(state, VerifyResult.Unresolved)); } } enumerator = stack.Pop(); if (!enumerator.MoveNext()) { continue; } } var stateCount = 0; proofState.Clear(); while (stateCount < VerifyNProofState) { var current = enumerator.Current; proofState.Add(current); stateCount++; if (backtrackList != null) { current.SetBackTrackCount(backtrackList); } if (current.NeedVerify && proofState[0].GetVerifyN() > 1) { current.DecreaseVerifyN(); current.NeedVerify = false; } if (!enumerator.MoveNext()) { break; } } //should at least one state in the list, use [0] as a typical state; var rep = proofState[0]; backtrackList = rep.GetBackTrackCount(); List <VerifyResult> ress = null; List <bool> returned = null; //check if any new added coded reuqires to call verifier, or reach the last line of code if ((rep.NeedVerify && rep.GetVerifyN() == 1) || rep.IsCurFrameEvaluated()) { foreach (var s in proofState) { s.ResetVerifyN(); s.NeedVerify = false; } bool backtracked = false; ress = VerifyState(proofState); returned = new List <bool>(); for (var i = 0; i < ress.Count; i++) { var res = ress[i]; var ret = false; switch (res) { case VerifyResult.Verified: //check if the frame are evaluated, as well as requiests for backtraking proofState[i].MarkCurFrameAsTerminated(true, out backtracked); if (backtracked) { lastSucc = proofState[i]; discarded.Add(new Tuple <ProofState, VerifyResult>(proofState[i], VerifyResult.Backtracked)); } if (proofState[i].IsTerminated()) { ret = true; yield return(proofState[i]); } returned.Add(ret); break; case VerifyResult.Failed: if (proofState[i].IsCurFrameEvaluated()) { proofState[i].MarkCurFrameAsTerminated(false, out backtracked); if (backtracked) { lastSucc = proofState[i]; discarded.Add(new Tuple <ProofState, VerifyResult>(proofState[i], VerifyResult.Backtracked)); } if (proofState[i].IsTerminated()) { ret = true; yield return(proofState[i]); } } returned.Add(ret); break; case VerifyResult.Unresolved: //Console.WriteLine("in unresolved"); discarded.Add(new Tuple <ProofState, VerifyResult>(proofState[i], VerifyResult.Unresolved)); //discard current branch if fails to resolve returned.Add(false); continue; default: throw new ArgumentOutOfRangeException(); } } } /* * when failed, check if this method is evaluated , i.e. all tstmt are evalauted, * if so, do nothing will dischard this branch and continue with the next one * otherwise, continue to evaluate the next stmt */ if (!rep.IsCurFrameEvaluated()) { //push the current one to the stack stack.Push(enumerator); //move to the next stmt for (var i = 0; i < proofState.Count; i++) { if (returned == null || !returned[i]) { stack.Push(proofState[i].EvalStep().GetEnumerator()); } } enumerator = stack.Pop(); } else { backtrackList = rep.GetBackTrackCount(); // update the current bc count to the list for (var i = 0; i < proofState.Count; i++) { if (returned == null || !returned[i]) { if (proofState[i].InAsserstion) { proofState[i].GetErrHandler().ErrType = TacticBasicErr.ErrorType.Assertion; var patchRes = proofState[i].ApplyPatch(); if (patchRes != null) { stack.Push(enumerator); enumerator = patchRes.GetEnumerator(); } } else { proofState[i].GetErrHandler().ErrType = TacticBasicErr.ErrorType.NotProved; } discarded.Add(new Tuple <ProofState, VerifyResult>(proofState[i], VerifyResult.Failed)); } } } } //check if over-backchecked if (backtrackList != null && backtrackList.Exists(x => x > 0)) { if (lastSucc == null) { Console.WriteLine("!!! No more branch for the request of " + (backtrackList.Last() + 1) + "backtracking, and no branch."); } else { Console.WriteLine("!!! No more branch for the request of " + lastSucc.GetOrignalTopBacktrack() + ", remaining " + (backtrackList.Last() + 1 > lastSucc.GetOrignalTopBacktrack() ? lastSucc.GetOrignalTopBacktrack() : backtrackList.Last() + 1) + " requests, return the last one."); yield return(lastSucc); } } else { // no result is successful ProofState s0; if (discarded.Count > 0) { s0 = discarded[discarded.Count - 1].Item1; //s0.GetErrHandler().ExceptionReport(); } else { s0 = rootState; } s0.ReportTacticError(s0.TopLevelTacApp.Tok, "No solution is found. \n The error message from the last failed branch: "); var errs = CompoundErrorInformation.GenerateErrorInfoList(s0); if (errDelegate != null) { foreach (var err in errs) { errDelegate(err); } } } }
public static IEnumerable <ProofState> EvalTopLevelTactic(ProofState state, Dictionary <IVariable, Type> variables, Statement tacticApplication, ApplySuffix aps, ErrorReporterDelegate errorDelegate, bool ifPartial) { Contract.Requires <ArgumentNullException>(Tcce.NonNull(variables)); Contract.Requires <ArgumentNullException>(Tcce.NonNull(tacticApplication)); Contract.Requires <ArgumentNullException>(state != null, "state"); Contract.Requires(tacticApplication == null || tacticApplication is UpdateStmt || tacticApplication is InlineTacticBlockStmt); IEnumerable <ProofState> branches; if (state.InitState(tacticApplication, aps, variables, ifPartial) == false) { return(null); } #if !TACNY_DEBUG try { #endif if (state.GetErrHandler().Reporter.Count(ErrorLevel.Error) != 0) { var errs = CompoundErrorInformation.GenerateErrorInfoList(state); if (errorDelegate != null) { foreach (var err in errs) { errorDelegate(err); } } return(null); } branches = GenerateSolution(state, errorDelegate); #if !TACNY_DEBUG } catch (Exception e) { String msg; List <CompoundErrorInformation> errs; try { msg = "Tactic unknown exception: " + e.Message; errs = CompoundErrorInformation.GenerateErrorInfoList(state, msg); } catch (Exception) { msg = "Tactic exception"; errs = new List <CompoundErrorInformation>(); } if (errorDelegate != null) { foreach (var err in errs) { errorDelegate(err); } } return(null); } #endif return(branches); }