public virtual Statement CloneStmt(Statement stmt) { if (stmt == null) { return null; } Statement r; if (stmt is AssertStmt) { var s = (AssertStmt)stmt; r = new AssertStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Expr), null); } else if (stmt is AssumeStmt) { var s = (AssumeStmt)stmt; r = new AssumeStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Expr), null); } else if (stmt is TacticInvariantStmt) { var s = (TacticInvariantStmt)stmt; r = new TacticInvariantStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Expr), null, s.IsObjectLevel); } else if (stmt is TacticAssertStmt) { var s = (TacticAssertStmt)stmt; r = new TacticAssertStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Expr), null, s.IsObjectLevel); } else if (stmt is PrintStmt) { var s = (PrintStmt)stmt; r = new PrintStmt(Tok(s.Tok), Tok(s.EndTok), s.Args.ConvertAll(CloneExpr)); } else if (stmt is BreakStmt) { var s = (BreakStmt)stmt; if (s.TargetLabel != null) { r = new BreakStmt(Tok(s.Tok), Tok(s.EndTok), s.TargetLabel); } else { r = new BreakStmt(Tok(s.Tok), Tok(s.EndTok), s.BreakCount); } } else if (stmt is ReturnStmt) { var s = (ReturnStmt)stmt; r = new ReturnStmt(Tok(s.Tok), Tok(s.EndTok), s.rhss == null ? null : s.rhss.ConvertAll(CloneRHS)); } else if (stmt is YieldStmt) { var s = (YieldStmt)stmt; r = new YieldStmt(Tok(s.Tok), Tok(s.EndTok), s.rhss == null ? null : s.rhss.ConvertAll(CloneRHS)); } else if (stmt is AssignStmt) { var s = (AssignStmt)stmt; r = new AssignStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Lhs), CloneRHS(s.Rhs)); } else if (stmt is BlockStmt) { r = CloneBlockStmt((BlockStmt)stmt); } else if (stmt is IfStmt) { var s = (IfStmt)stmt; r = new IfStmt(Tok(s.Tok), Tok(s.EndTok), s.IsExistentialGuard, CloneExpr(s.Guard), CloneBlockStmt(s.Thn), CloneStmt(s.Els)); } else if (stmt is AlternativeStmt) { var s = (AlternativeStmt)stmt; r = new AlternativeStmt(Tok(s.Tok), Tok(s.EndTok), s.Alternatives.ConvertAll(CloneGuardedAlternative)); } else if (stmt is WhileStmt) { var s = (WhileStmt)stmt; r = new WhileStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Guard), s.Invariants.ConvertAll(CloneMayBeFreeExpr), CloneSpecExpr(s.Decreases), CloneSpecFrameExpr(s.Mod), CloneBlockStmt(s.Body)); ((WhileStmt)r).TacAps = s.TacAps; } else if (stmt is AlternativeLoopStmt) { var s = (AlternativeLoopStmt)stmt; r = new AlternativeLoopStmt(Tok(s.Tok), Tok(s.EndTok), s.Invariants.ConvertAll(CloneMayBeFreeExpr), CloneSpecExpr(s.Decreases), CloneSpecFrameExpr(s.Mod), s.Alternatives.ConvertAll(CloneGuardedAlternative)); } else if (stmt is ForallStmt) { var s = (ForallStmt)stmt; r = new ForallStmt(Tok(s.Tok), Tok(s.EndTok), s.BoundVars.ConvertAll(CloneBoundVar), null, CloneExpr(s.Range), s.Ens.ConvertAll(CloneMayBeFreeExpr), CloneStmt(s.Body)); if (s.ForallExpressions != null) { ((ForallStmt)r).ForallExpressions = s.ForallExpressions.ConvertAll(CloneExpr); } } else if (stmt is CalcStmt) { var s = (CalcStmt)stmt; // calc statements have the unusual property that the last line is duplicated. If that is the case (which // we expect it to be here), we share the clone of that line as well. var lineCount = s.Lines.Count; var lines = new List<Expression>(lineCount); for (int i = 0; i < lineCount; i++) { lines.Add(i == lineCount - 1 && 2 <= lineCount && s.Lines[i] == s.Lines[i - 1] ? lines[i - 1] : CloneExpr(s.Lines[i])); } Contract.Assert(lines.Count == lineCount); r = new CalcStmt(Tok(s.Tok), Tok(s.EndTok), CloneCalcOp(s.Op), lines, s.Hints.ConvertAll(CloneBlockStmt), s.StepOps.ConvertAll(CloneCalcOp), CloneCalcOp(s.ResultOp), CloneAttributes(s.Attributes)); } else if (stmt is MatchStmt) { var s = (MatchStmt)stmt; r = new MatchStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Source), s.Cases.ConvertAll(CloneMatchCaseStmt), s.UsesOptionalBraces); } else if (stmt is AssignSuchThatStmt) { var s = (AssignSuchThatStmt)stmt; r = new AssignSuchThatStmt(Tok(s.Tok), Tok(s.EndTok), s.Lhss.ConvertAll(CloneExpr), CloneExpr(s.Expr), s.AssumeToken == null ? null : Tok(s.AssumeToken), null); } else if (stmt is UpdateStmt) { var s = (UpdateStmt)stmt; r = new UpdateStmt(Tok(s.Tok), Tok(s.EndTok), s.Lhss.ConvertAll(CloneExpr), s.Rhss.ConvertAll(CloneRHS), s.CanMutateKnownState); } else if (stmt is VarDeclStmt) { var s = (VarDeclStmt)stmt; var lhss = s.Locals.ConvertAll(c => new LocalVariable(Tok(c.Tok), Tok(c.EndTok), c.Name, CloneType(c.OptionalType), c.IsGhost)); r = new VarDeclStmt(Tok(s.Tok), Tok(s.EndTok), lhss, (ConcreteUpdateStatement)CloneStmt(s.Update)); } else if (stmt is LetStmt) { var s = (LetStmt)stmt; r = new LetStmt(Tok(s.Tok), Tok(s.EndTok), s.LHSs.ConvertAll(CloneCasePattern), s.RHSs.ConvertAll(CloneExpr)); } else if (stmt is ModifyStmt) { var s = (ModifyStmt)stmt; var mod = CloneSpecFrameExpr(s.Mod); var body = s.Body == null ? null : CloneBlockStmt(s.Body); r = new ModifyStmt(Tok(s.Tok), Tok(s.EndTok), mod.Expressions, mod.Attributes, body); } else if (stmt is TacnyCasesBlockStmt) { var s = (TacnyCasesBlockStmt)stmt; var guard = CloneExpr(s.Guard); var body = s.Body == null ? null : CloneBlockStmt(s.Body); r = new TacnyCasesBlockStmt(Tok(s.Tok), Tok(s.EndTok), guard, body); } else if (stmt is TacnyChangedBlockStmt) { var s = (TacnyChangedBlockStmt)stmt; var body = s.Body == null ? null : CloneBlockStmt(s.Body); r = new TacnyChangedBlockStmt(Tok(s.Tok), Tok(s.EndTok), body); } else if (stmt is TacnySolvedBlockStmt) { var s = (TacnySolvedBlockStmt)stmt; var body = s.Body == null ? null : CloneBlockStmt(s.Body); r = new TacnySolvedBlockStmt(Tok(s.Tok), Tok(s.EndTok), body); } else if (stmt is TacnyTryCatchBlockStmt) { var s = (TacnyTryCatchBlockStmt)stmt; var body = s.Body == null ? null : CloneBlockStmt(s.Body); var c = s.Ctch == null ? null : CloneBlockStmt(s.Ctch); r = new TacnyTryCatchBlockStmt(Tok(s.Tok), Tok(s.EndTok), body, c); } else if (stmt is TacticVarDeclStmt) { var s = (TacticVarDeclStmt)stmt; var lhss = s.Locals.ConvertAll(c => new LocalVariable(Tok(c.Tok), Tok(c.EndTok), c.Name, CloneType(c.OptionalType), c.IsGhost)); r = new TacticVarDeclStmt(Tok(s.Tok), Tok(s.EndTok), lhss, (ConcreteUpdateStatement)CloneStmt(s.Update)); } else { Contract.Assert(false); throw new cce.UnreachableException(); // unexpected statement } // add labels to the cloned statement AddStmtLabels(r, stmt.Labels); r.Attributes = CloneAttributes(stmt.Attributes); return r; }
void TacnyCasesBlockStmt(out Statement/*!*/ tacnyCasesStmt, IToken x) { Contract.Ensures(Contract.ValueAtReturn(out tacnyCasesStmt) != null); Expression guard = null; IToken guardEllipsis = null; BlockStmt/*!*/ thn; Attributes attrs = null; IToken bodyStart, bodyEnd, endTok; List<GuardedAlternative> alternatives; tacnyCasesStmt = dummyStmt; // to please the compiler if(IsAlternative()) { AlternativeBlock(true, out alternatives, out endTok); tacnyCasesStmt = new AlternativeStmt(x, endTok, alternatives); } else if(StartOf(22)) { if(StartOf(23)) { Guard(out guard); } else { Get(); guardEllipsis = t; } while(IsAttribute()) { Attribute(ref attrs); } BlockStmt(out thn, out bodyStart, out bodyEnd); endTok = thn.EndTok; if(guardEllipsis != null) { tacnyCasesStmt = new SkeletonStatement(new TacnyCasesBlockStmt(x, endTok, guard, attrs, thn), guardEllipsis, null); } else { tacnyCasesStmt = new TacnyCasesBlockStmt(x, endTok, guard, attrs, thn); } } else SynErr(217); }
private Solution GenerateVerifiedStmt(DatatypeDecl datatype, NameSegment casesGuard, TacnyCasesBlockStmt st) { bool[] ctorFlags; int ctor; // current active match case InitCtorFlags(datatype, out ctorFlags); List <Solution> ctorBodies = RepeatedDefault <Solution>(datatype.Ctors.Count); // find the first failing case MatchStmt ms = GenerateMatchStmt(DynamicContext.tac_call.Tok.line, Util.Copy.CopyNameSegment(casesGuard), datatype, ctorBodies); Solution solution = CreateSolution(this, ms); if (!ResolveAndVerify(solution)) { ctor = 0; } else { ctor = GetErrorIndex(StaticContext.program.GetErrorToken(), ms); // the error is occuring outside the match stmt if (ctor == -1) { ms = GenerateMatchStmt(DynamicContext.tac_call.Tok.line, Util.Copy.CopyNameSegment(casesGuard), datatype, ctorBodies); return(CreateSolution(this, ms)); } ctorFlags[ctor] = true; _oldToken = StaticContext.program.GetErrorToken(); } while (ctor < datatype.Ctors.Count) { if (!StaticContext.program.HasError()) { break; } RegisterLocals(datatype, ctor, _ctorTypes); // if nothing was generated for the cases body move on to the next one foreach (var result in ResolveBody(st.Body)) { ctorBodies[ctor] = result; ms = GenerateMatchStmt(DynamicContext.tac_call.Tok.line, Util.Copy.CopyNameSegment(casesGuard), datatype, ctorBodies); solution = CreateSolution(this, ms); // if the program fails tro resolve skip if (!ResolveAndVerify(solution)) { continue; } if (!StaticContext.program.HasError()) { break; } if (CheckError(ms, ref ctorFlags, ctor)) { // if the ctor does not require a body null the value if (!ctorFlags[ctor]) { ctorBodies[ctor] = null; } break; } } // clear local var RemoveLocals(datatype, ctor); ctor++; } ms = GenerateMatchStmt(DynamicContext.tac_call.Tok.line, Util.Copy.CopyNameSegment(casesGuard), datatype, ctorBodies); return(CreateSolution(this, ms)); }
private IEnumerable <Solution> GenerateMatch(TacnyCasesBlockStmt st) { NameSegment casesGuard; UserDefinedType datatypeType = null; var isElement = false; var guard = st.Guard as ParensExpression; if (guard == null) { casesGuard = st.Guard as NameSegment; } else { casesGuard = guard.E as NameSegment; } Contract.Assert(casesGuard != null, Error.MkErr(st, 2)); IVariable tacInput = GetLocalKeyByName(casesGuard); Contract.Assert(tacInput != null, Error.MkErr(st, 9, casesGuard.Name)); if (!(tacInput is Formal)) { tacInput = GetLocalValueByName(casesGuard) as IVariable; Contract.Assert(tacInput != null, Error.MkErr(st, 9, casesGuard.Name)); // the original if (tacInput != null) { casesGuard = new NameSegment(tacInput.Tok, tacInput.Name, null); } } else { // get the original declaration inside the method casesGuard = GetLocalValueByName(tacInput) as NameSegment; } string datatypeName = tacInput?.Type.ToString(); /** * TODO cleanup * if datatype is Element lookup the formal in global variable registry */ if (datatypeName == "Element") { isElement = true; var val = GetLocalValueByName(tacInput.Name); var decl = val as NameSegment; Contract.Assert(decl != null, Error.MkErr(st, 9, tacInput.Name)); var originalDecl = StaticContext.GetGlobalVariable(decl?.Name); if (originalDecl != null) { datatypeType = originalDecl.Type as UserDefinedType; datatypeName = datatypeType != null ? datatypeType.Name : originalDecl.Type.ToString(); } else { Contract.Assert(false, Error.MkErr(st, 9, tacInput.Name)); } } if (!StaticContext.ContainsGlobalKey(datatypeName)) { Contract.Assert(false, Error.MkErr(st, 12, datatypeName)); } var datatype = StaticContext.GetGlobal(datatypeName); if (datatype.TypeArgs != null) { _ctorTypes = new Dictionary <string, Type>(); if (datatype.TypeArgs.Count == datatypeType.TypeArgs.Count) { for (int i = 0; i < datatype.TypeArgs.Count; i++) { var genericType = datatype.TypeArgs[i]; var definedType = datatypeType.TypeArgs[i]; _ctorTypes.Add(genericType.Name, definedType); } } } if (isElement) { yield return(GenerateVerifiedStmt(datatype, casesGuard, st)); } else { foreach (var item in GenerateStmt(datatype, casesGuard, st)) { yield return(item); } } }
/// <summary> /// TODO: Resolve the bodies lazily /// </summary> /// <param name="datatype"></param> /// <param name="casesGuard"></param> /// <param name="st"></param> /// <returns></returns> private IEnumerable <Solution> GenerateStmt(DatatypeDecl datatype, NameSegment casesGuard, TacnyCasesBlockStmt st) { List <List <Solution> > allCtorBodies = Repeated(new List <Solution>(), datatype.Ctors.Count); int ctor = 0; foreach (var list in allCtorBodies) { list.Add(null); RegisterLocals(datatype, ctor); foreach (var result in ResolveBody(st.Body)) { list.Add(result); } RemoveLocals(datatype, ctor); ctor++; } foreach (var stmt in GenerateAllMatchStmt(DynamicContext.tac_call.Tok.line, 0, Util.Copy.CopyNameSegment(casesGuard), datatype, allCtorBodies, new List <Solution>())) { yield return(CreateSolution(this, stmt)); } }