public LemmaDecl GenerateEmptyBlockLemma(Block block, IEnumerable <Block> finalCfgSuccessors, string lemmaName) { //Term cmds = new TermList(cmdIsaVisitor.Translate(block.Cmds)); var blockDefName = isaBlockInfo.CmdsQualifiedName(block); Term blockDefTerm = IsaCommonTerms.TermIdentFromName(blockDefName); var cmdsReduce = IsaBoogieTerm.RedCmdList(boogieContext, blockDefTerm, initState, finalState); var assumptions = new List <Term> { cmdsReduce }; if (finalCfgSuccessors.Any()) { assumptions.Add(LemmaHelper.ConjunctionOfSuccessorBlocks(finalCfgSuccessors, declToVCMapping, vcinst)); } var conclusion = ConclusionBlock(finalCfgSuccessors, normalInitState, finalState, declToVCMapping, vcinst); var proof = new Proof( new List <string> { "using assms", "unfolding " + blockDefName + "_def", "apply cases", "by auto" } ); return(new LemmaDecl(lemmaName, ContextElem.CreateWithAssumptions(assumptions), conclusion, proof)); }
private ContextElem LemmaContext( CFGRepr cfg, Term vcAssm ) { var multiRed = IsaBoogieTerm.RedCFGMulti( BoogieContextIsa.CreateWithNewVarContext( boogieContext, new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl()) ), programAccessor.CfgDecl(), IsaBoogieTerm.CFGConfigNode(new NatConst(cfg.GetUniqueIntLabel(cfg.entry)), IsaBoogieTerm.Normal(normalInitState)), IsaBoogieTerm.CFGConfig(finalNodeOrReturn, finalState) ); var closedAssm = EndToEndAssumptions.ClosednessAssumption(boogieContext.absValTyMap); var nonEmptyTypesAssm = EndToEndAssumptions.NonEmptyTypesAssumption(boogieContext.absValTyMap); var finterpAssm = IsaBoogieTerm.FunInterpWf(boogieContext.absValTyMap, programAccessor.FunctionsDecl(), boogieContext.funContext); var absValType = new VarType("a"); //need to explicitly give type for normal state, otherwise Isabelle won't know that the abstract value type is the same as used in the VC var axiomAssm = EndToEndAssumptions.AxiomAssumption(boogieContext, programAccessor, new TermWithExplicitType(normalInitState, IsaBoogieType.NormalStateType(absValType))); var presAssm = IsaBoogieTerm.ExprAllSat(boogieContext, normalInitState, programAccessor.PreconditionsDecl()); var localsAssm = EndToEndAssumptions.LocalStateAssumption(boogieContext, IsaCommonTerms.Snd(boogieContext.varContext), normalInitState); var globalsAssm = EndToEndAssumptions.GlobalStateAssumption(boogieContext, IsaCommonTerms.Fst(boogieContext.varContext), normalInitState); var oldGlobalStateAssm = EndToEndAssumptions.OldGlobalStateAssumption(normalInitState); var binderEmptyAssm = EndToEndAssumptions.BinderStateEmpty(normalInitState); return (ContextElem.CreateWithAssumptions( new List <Term> { multiRed, vcAssm, closedAssm, nonEmptyTypesAssm, finterpAssm, axiomAssm, presAssm, localsAssm, globalsAssm, oldGlobalStateAssm, binderEmptyAssm }, new List <string> { redAssmName, vcAssmName, closedAssmName, nonEmptyTypesAssmName, finterpAssmName, axiomAssmName, preconditionsAssmName, paramsLocalsAssmName, constsGlobalsAssmName, oldGlobalAssmName, binderEmptyAssmName } )); }
public LemmaDecl GenerateBlockLemma(Block block, Block finalCfgBlock, IEnumerable <Block> finalCfgSuccessors, string lemmaName, string vcHintsName) { var cmdsReduce = IsaBoogieTerm.RedCmdList(boogieContext, IsaCommonTerms.TermIdentFromName(isaBlockInfo.CmdsQualifiedName(block)), initState, finalState); var vcAssm = vcinst.GetVCObjInstantiation(finalCfgBlock, declToVCMapping); //do not use separate assumption, leads to issues var conclusion = ConclusionBlock(finalCfgSuccessors, normalInitState, finalState, declToVCMapping, vcinst, LemmaHelper.FinalStateIsMagic(block)); Term statement = TermBinary.MetaImplies(cmdsReduce, TermBinary.MetaImplies(vcAssm, conclusion)); var proof = BlockCorrectProof(block, finalCfgBlock, vcHintsName); return(new LemmaDecl(lemmaName, ContextElem.CreateEmptyContext(), statement, proof)); }
public LemmaDecl AxiomVcLemma(string lemmaName, Axiom axiom, VCExpr vcAxiom, out IList <OuterDecl> requiredDecls) { var vc = vcAxiomInst.GetVCObjInstantiation(vcAxiom, declToVCMapping); var axiomTerm = basicCmdIsaVisitor.Translate(axiom.Expr); requiredDecls = new List <OuterDecl>(); vcRewriteLemmaGen.RequiredVcRewrite(axiom.Expr, true, out var vcRewriteLemmas); VCExprHint exprHint; if (vcRewriteLemmas != null && vcRewriteLemmas.Any()) { exprHint = new VCExprHint(vcRewriteLemmas); requiredDecls.AddRange(vcRewriteLemmas); } else { exprHint = VCExprHint.EmptyExprHint(); } var assumption = IsaBoogieTerm.RedExpr(boogieContext, axiomTerm, normalInitState, IsaBoogieTerm.BoolVal(true)); var statement = vc; return (new LemmaDecl(lemmaName, ContextElem.CreateWithAssumptions(assumption), statement, new Proof(new List <string> { "unfolding " + vcAxiomInst.GetVCObjNameRef(vcAxiom) + "_def", ProofUtil.By( ProofUtil.MLTactic( "prove_axiom_vc_tac @{context} (" + exprHint.GetMLString() + ") " + MLUtil.IsaToMLThm("assms(1)") + " " + MLUtil.IsaToMLThms(globalAssmsName) + " (@{thm forall_poly_thm}, @{thm exists_poly_thm}) []", 1) ) }) )); }
public IEnumerable <OuterDecl> EndToEndProof( string entryCfgLemma, string passificationEndToEndLemma, Term vcAssm, IProgramAccessor programAccessor, CFGRepr cfg) { this.programAccessor = programAccessor; boogieContext = new BoogieContextIsa( IsaCommonTerms.TermIdentFromName("A"), IsaCommonTerms.TermIdentFromName("M"), IsaCommonTerms.TermIdentFromName(varContextName), IsaCommonTerms.TermIdentFromName("\\<Gamma>"), IsaCommonTerms.EmptyList ); var abbrev = new AbbreviationDecl( varContextName, new Tuple <IList <Term>, Term>(new List <Term>(), new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl())) ); var result = new List <OuterDecl> { abbrev }; var kStepRed = IsaBoogieTerm.RedCFGKStep( BoogieContextIsa.CreateWithNewVarContext( boogieContext, new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl()) ), programAccessor.CfgDecl(), IsaBoogieTerm.CFGConfigNode(new NatConst(cfg.GetUniqueIntLabel(cfg.entry)), IsaBoogieTerm.Normal(normalInitState)), IsaCommonTerms.TermIdentFromName("j"), IsaBoogieTerm.CFGConfig(finalNodeOrReturn, finalState) ); var proofSb = new StringBuilder(); proofSb.AppendLine("proof -"); proofSb.AppendLine("from " + redAssmName + " obtain j where Aux:" + "\"" + kStepRed + "\""); proofSb.AppendLine("by (meson rtranclp_imp_relpowp)"); proofSb.AppendLine("show ?thesis"); proofSb.AppendLine(ProofUtil.Apply("rule " + entryCfgLemma)); //TODO: don't hardcode this proofSb.AppendLine("unfolding cfg_to_dag_lemmas_def"); proofSb.AppendLine(ProofUtil.Apply("rule " + finterpAssmName)); proofSb.AppendLine("apply (rule Aux)"); proofSb.AppendLine("apply (rule dag_lemma_assms_same)"); proofSb.AppendLine("unfolding state_well_typed_def"); proofSb.AppendLine("apply (intro conjI)"); proofSb.AppendLine("using " + paramsLocalsAssmName + " apply simp"); proofSb.AppendLine("using " + constsGlobalsAssmName + " apply simp"); proofSb.AppendLine("using " + constsGlobalsAssmName + " " + oldGlobalAssmName + " apply simp"); proofSb.AppendLine("using " + binderEmptyAssmName + " apply simp"); proofSb.AppendLine(ProofUtil.Apply("rule " + passificationEndToEndLemma)); //TODO: don't hardcode this proofSb.AppendLine("unfolding glue_proof_def"); proofSb.AppendLine("apply (intro conjI)"); proofSb.AppendLine("apply assumption"); proofSb.AppendLine("using " + vcAssmName + " apply simp"); proofSb.AppendLine("using " + closedAssmName + " apply simp"); proofSb.AppendLine("using " + nonEmptyTypesAssmName + " apply simp"); proofSb.AppendLine(ProofUtil.Apply("rule " + finterpAssmName)); proofSb.AppendLine("using " + axiomAssmName + " apply simp"); proofSb.AppendLine("using " + paramsLocalsAssmName + " apply simp"); proofSb.AppendLine("using " + constsGlobalsAssmName + " apply simp"); proofSb.AppendLine("using " + binderEmptyAssmName + " apply simp"); proofSb.AppendLine("using " + oldGlobalAssmName + " apply simp"); proofSb.AppendLine("using " + preconditionsAssmName + " apply simp"); proofSb.AppendLine("done"); proofSb.AppendLine("qed"); var helperLemmaName = "end_to_end_theorem_aux"; var helperLemma = new LemmaDecl( helperLemmaName, LemmaContext(cfg, vcAssm), CfgToDagLemmaManager.CfgLemmaConclusion(boogieContext, programAccessor.PostconditionsDecl(), finalNodeOrReturn, finalState), new Proof(new List <string> { proofSb.ToString() }) ); result.Add(helperLemma); //transform end to end theorem to a compact representation var endToEndLemma = new LemmaDecl( "end_to_end_theorem", ContextElem.CreateWithAssumptions(new List <Term> { vcAssm }, new List <string> { "VC" }), ProcedureIsCorrect( programAccessor.FunctionsDecl(), IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()), IsaCommonTerms.TermIdentFromName(programAccessor.GlobalsDecl()), programAccessor.AxiomsDecl(), programAccessor.ProcDecl()), new Proof( new List <string> { ProofUtil.Apply(ProofUtil.Rule(ProofUtil.OF("end_to_end_util", helperLemmaName))), "apply assumption " + "using VC apply simp " + " apply assumption+", ProofUtil.By("simp_all add: exprs_to_only_checked_spec_1 exprs_to_only_checked_spec_2 " + programAccessor.ProcDeclName() + "_def " + programAccessor.CfgDeclName() + "_def") } )); result.Add(endToEndLemma); return(result); }
public int PrintContextElem(ContextElem c) { if (c.FixedVariables.Count > 0) { _sb.Append("fixes "); var first = true; foreach (var fix in c.FixedVariables) { if (first) { first = false; } else { _sb.Append(" and "); } _sb.Append(fix.Item1.Dispatch(_termPrinter)); _sb.Append(" :: "); AppendInner(fix.Item2.Dispatch(_typeIsaPrinter)); } } if (c.Assumptions.Count > 0) { var useAssmLabels = c.AssmLabels.Count == c.Assumptions.Count; var assmLabelEnumerator = c.AssmLabels.GetEnumerator(); assmLabelEnumerator.MoveNext(); if (c.FixedVariables.Count > 0) { _sb.AppendLine(); } _sb.AppendLine("assumes "); var first = true; foreach (var t in c.Assumptions) { if (first) { first = false; } else { _sb.Append(" and "); _sb.AppendLine(); } if (useAssmLabels) { _sb.Append(assmLabelEnumerator.Current); _sb.Append(": "); assmLabelEnumerator.MoveNext(); } AppendInner(t.Dispatch(_termPrinter)); } } return(0); }
public static LocaleDecl ConvertVC( string localeName, VCExpr vc, IEnumerable <VCExpr> vcAxioms, IActiveDeclGenerator activeDeclGenerator, Boogie2VCExprTranslator translator, TypeAxiomBuilderPremisses axiomBuilder, BoogieMethodData methodData, CFGRepr cfg, out VCInstantiation <Block> vcinst, out VCInstantiation <VCExpr> vcinstAxiom, out IVCVarFunTranslator vcTranslator, out IEnumerable <Function> vcTypeFunctions) { var vcLet = vc as VCExprLet; Contract.Assert(vcLet != null); var uniqueNamer = new IsaUniqueNamer(); var blockToVC = VCBlockExtractor.BlockToVCMapping(vcLet, cfg); var declCollector = new VCFunDeclCollector(); var funToVCfun = declCollector.CollectFunDeclarations(new List <VCExpr> { vc }.Concat(vcAxioms), methodData.Functions); IVCVarFunTranslator varTranslator = new VCVarFunTranslator(methodData.AllVariables(), funToVCfun, translator, axiomBuilder); var activeDeclsPerBlock = activeDeclGenerator.GetActiveDeclsPerBlock(blockToVC, varTranslator, cfg, out var blockToNewVars); #region temporary: extend vc instantiation to support vc functions IList <Function> otherFunctions = new List <Function>(); ISet <Function> otherFunctionsSet = new HashSet <Function>(); foreach (var decl in activeDeclsPerBlock[cfg.entry]) { if (decl is Function fun && !varTranslator.TranslateBoogieFunction(fun, out _)) { otherFunctions.Add(fun); otherFunctionsSet.Add(fun); } } //also record functions that are used elswhere (type axiom related functions) var collector = new VCExprDeclCollector(); var vcExprs = vcAxioms.ToList(); foreach (var ax in vcExprs) { var decls = collector.CollectNamedDeclarations(ax, varTranslator); foreach (var d in decls) { if (d is Function fun && !varTranslator.TranslateBoogieFunction(fun, out _) && !otherFunctions.Contains(d)) { otherFunctions.Add(fun); } } } #endregion IDictionary <Block, IList <NamedDeclaration> > activeDeclsPerBlockSorted = SortActiveDecls(activeDeclsPerBlock, methodData.Functions.Union(otherFunctions), varTranslator, out var activeVarsPerBlock); var blockToNewVCVars = ConvertVariableToVCExpr(blockToNewVars, varTranslator); var blockToIsaTranslator = new VCBlockToIsaTranslator(uniqueNamer); var blockToVCExpr = blockToIsaTranslator.IsaDefsFromVC(blockToVC, activeVarsPerBlock, cfg, blockToNewVCVars); //add vc definitions of blocks in correct order IList <OuterDecl> vcOuterDecls = new List <OuterDecl>(); foreach (var block in cfg.GetBlocksBackwards()) { vcOuterDecls.Add(blockToVCExpr[block]); } vcinst = new VCInstantiation <Block>(blockToVCExpr, activeDeclsPerBlockSorted, localeName); /* * * //reason for using second reference: cannot use out parameters in lambda expressions * var vcinstInternal = vcinst; * * LemmaDecl vcCorrectLemma = new LemmaDecl("vc_correct", * new TermApp(vcinstInternal.GetVCObjRef(cfg.entry, false), * activeVarsPerBlock[cfg.entry].Select(v => (Term) IsaCommonTerms.TermIdentFromName(uniqueNamer.GetName(v, v.Name))).ToList()), * new Proof( * new List<string>() { * "apply (simp only: " + * cfg.GetBlocksForwards().Select(b => vcinstInternal.GetVCObjNameRef(b, false) + "_def").Concat(" ") + ")", + "oops" + } + )); + + vcOuterDecls.Add(vcCorrectLemma); */ //axioms var activeDeclsPerAxiom = VCInstAxioms(vcExprs, varTranslator); IDictionary <VCExpr, IList <NamedDeclaration> > activeDeclsPerAxiomSorted = SortActiveDecls(activeDeclsPerAxiom, methodData.Functions.Union(otherFunctions), varTranslator, out var activeVarsPerAxiom); var axiomToDef = new Dictionary <VCExpr, DefDecl>(); var vcExprIsaTranslator = new VCExprToIsaTranslator(uniqueNamer); if (activeDeclsPerAxiomSorted.Count != vcExprs.Count()) { throw new ProofGenUnexpectedStateException(typeof(VCToIsaInterface), "count not in-sync"); } var axId = 0; foreach (var vcAx in activeDeclsPerAxiomSorted.Keys) { IList <Term> args = activeVarsPerAxiom[vcAx].Select(v => vcExprIsaTranslator.Translate(v)).ToList(); var rhs = vcExprIsaTranslator.Translate(vcAx); var def = new DefDecl("vcax_" + axId, new Tuple <IList <Term>, Term>(args, rhs)); axiomToDef.Add(vcAx, def); axId++; } vcinstAxiom = new VCInstantiation <VCExpr>(axiomToDef, activeDeclsPerAxiomSorted, localeName); vcOuterDecls.AddRange(axiomToDef.Values); var vcFunctions = methodData.Functions.Where(f => varTranslator.TranslateBoogieFunction(f, out var result)) .Select(f => { if (varTranslator.TranslateBoogieFunction(f, out var result)) { return(result); } throw new InvalidOperationException(); }).Union(otherFunctions); vcTranslator = varTranslator; vcTypeFunctions = otherFunctions; return(new LocaleDecl(localeName, ContextElem.CreateWithFixedVars(GetVarsInVC(vcFunctions, uniqueNamer)), vcOuterDecls)); }
public LemmaDecl GenerateCfgLemma( Block block, Block finalCfgBlock, bool isContainedInFinalCfg, IEnumerable <Block> successors, IEnumerable <Block> finalCfgSuccessors, Term cfg, Func <Block, string> cfgLemmaName, LemmaDecl BlockLemma) { var red = IsaBoogieTerm.RedCFGMulti( boogieContext, cfg, IsaBoogieTerm.CFGConfigNode(new NatConst(isaBlockInfo.BlockIds[block]), IsaBoogieTerm.Normal(normalInitState)), IsaBoogieTerm.CFGConfig(finalNode, finalState)); var assumption = new List <Term> { red }; var hasVcAssm = false; if (isContainedInFinalCfg) { assumption.Add(vcinst.GetVCObjInstantiation(finalCfgBlock, declToVCMapping)); hasVcAssm = true; } else { //vc assumption is conjunction of reachable successors in final cfg if (finalCfgSuccessors.Any()) { assumption.Add( LemmaHelper.ConjunctionOfSuccessorBlocks(finalCfgSuccessors, declToVCMapping, vcinst)); hasVcAssm = true; } } Term conclusion = new TermBinary(finalState, IsaBoogieTerm.Failure(), TermBinary.BinaryOpCode.Neq); var nodeLemma = isaBlockInfo.BlockCmdsMembershipLemma(block); var outEdgesLemma = isaBlockInfo.OutEdgesMembershipLemma(block); var proofMethods = new List <string>(); var eruleLocalBlock = "erule " + (hasVcAssm ? ProofUtil.OF(BlockLemma.Name, "_", "assms(2)") : BlockLemma.Name); if (isContainedInFinalCfg && LemmaHelper.FinalStateIsMagic(block)) { proofMethods.Add("apply (rule converse_rtranclpE2[OF assms(1)], fastforce)"); proofMethods.Add(ProofUtil.Apply("rule " + ProofUtil.OF("red_cfg_multi_backwards_step_magic", "assms(1)", nodeLemma))); proofMethods.Add(ProofUtil.By(eruleLocalBlock)); return(new LemmaDecl(cfgLemmaName(block), ContextElem.CreateWithAssumptions(assumption), conclusion, new Proof(proofMethods))); } if (successors.Any()) { proofMethods.Add("apply (rule converse_rtranclpE2[OF assms(1)], fastforce)"); var cfg_lemma = finalCfgSuccessors.Any() ? "red_cfg_multi_backwards_step" : "red_cfg_multi_backwards_step_2"; proofMethods.Add(ProofUtil.Apply("rule " + ProofUtil.OF(cfg_lemma, "assms(1)", nodeLemma))); proofMethods.Add(ProofUtil.Apply(eruleLocalBlock)); proofMethods.Add("apply (" + ProofUtil.Simp(outEdgesLemma) + ")"); foreach (var bSuc in successors) { proofMethods.Add("apply (erule member_elim, simp)"); proofMethods.Add("apply (erule " + cfgLemmaName(bSuc) + ", simp?" + ")"); } proofMethods.Add("by (simp add: member_rec(2))"); } else { proofMethods.Add("apply (rule converse_rtranclpE2[OF assms(1)], fastforce)"); proofMethods.Add("apply (rule " + ProofUtil.OF("red_cfg_multi_backwards_step_no_succ", "assms(1)", nodeLemma, outEdgesLemma) + ")"); if (isContainedInFinalCfg) { proofMethods.Add("using " + ProofUtil.OF(BlockLemma.Name, "_", "assms(2)") + " by blast"); } else { proofMethods.Add("using " + BlockLemma.Name + " by blast"); } } return(new LemmaDecl(cfgLemmaName(block), ContextElem.CreateWithAssumptions(assumption), conclusion, new Proof(proofMethods))); }