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 override int VisitAbbreviationDecl(AbbreviationDecl d) { return(HandleAbbrevOrDef(d, "abbreviation", d.Type, "\\<equiv>", d.Equation)); }
public static Theory PassificationProof( string theoryName, string boogieToVcTheoryName, bool generateEndToEndLemma, LemmaDecl boogieToVcLemma, Term vcAssm, CFGRepr beforePassificationCfg, IDictionary <Block, Block> nonPassiveToPassiveBlock, PassiveRelationGen relationGen, IProgramAccessor beforePassiveProgAccess, IProgramAccessor passiveProgAccess, BoogieMethodData beforePassiveData, IVariableTranslationFactory beforePassiveFactory, IVariableTranslationFactory passiveFactory) { var varContextName = "\\<Lambda>1"; var passiveVarContextName = "\\<Lambda>2"; var varContextNonPassivePassive = Tuple.Create(varContextName, passiveVarContextName); var oldGlobalVars = GetOldGlobalVariables(beforePassificationCfg); var oldRelationData = OldRelation( oldGlobalVars, beforePassiveFactory.CreateTranslation().VarTranslation, out var oldRelListDecl); var passificationProofDecls = new List <OuterDecl>(); passificationProofDecls.AddRange(oldRelListDecl); passificationProofDecls.AddRange(oldRelationData.VarToLookupLemma.Values); if (oldRelationData.VarToLookupLemma.Any()) { passificationProofDecls.Add(new LemmasDecl(allOldLookupLemmasName, oldRelationData.VarToLookupLemma.Values.Select(lemma => lemma.Name).ToList())); } var beforePassiveLemmaManager = new PassificationLemmaManager( beforePassificationCfg, nonPassiveToPassiveBlock, beforePassiveProgAccess, passiveProgAccess, varContextNonPassivePassive, oldRelationData, relationGen, beforePassiveFactory, passiveFactory ); var lemmaNamer = new IsaUniqueNamer(); var varContextAbbrev = new AbbreviationDecl( varContextName, new Tuple <IList <Term>, Term>(new List <Term>(), beforePassiveProgAccess.VarContext()) ); var passiveVarContextAbbrev = new AbbreviationDecl( passiveVarContextName, new Tuple <IList <Term>, Term>(new List <Term>(), passiveProgAccess.VarContext()) ); passificationProofDecls.Add(varContextAbbrev); passificationProofDecls.Add(passiveVarContextAbbrev); passificationProofDecls.AddRange(beforePassiveLemmaManager.Prelude()); var cfgLemmas = new List <OuterDecl>(); foreach (var block in beforePassificationCfg.GetBlocksBackwards()) { var localAndCfgLemma = beforePassiveLemmaManager.GenerateBlockLemma( block, GetLemmaName(block, lemmaNamer), b => GetCfgLemmaName(b, lemmaNamer)); passificationProofDecls.Add(localAndCfgLemma.Item1); cfgLemmas.Add(localAndCfgLemma.Item2); } //add cfg lemmas at the end passificationProofDecls.AddRange(cfgLemmas); if (generateEndToEndLemma) { var endToEnd = new PassificationEndToEnd(); passificationProofDecls.AddRange(endToEnd.EndToEndProof( GetCfgLemmaName(beforePassificationCfg.entry, lemmaNamer), boogieToVcTheoryName + "." + boogieToVcLemma.Name, vcAssm, beforePassiveProgAccess, passiveProgAccess, varContextNonPassivePassive, oldRelationData, beforePassificationCfg, relationGen.LiveVarsBeforeBlock(beforePassificationCfg.entry), passiveFactory.CreateTranslation().VarTranslation )); } var imports = new List <string> { "Boogie_Lang.Semantics", "Boogie_Lang.Util", beforePassiveProgAccess.TheoryName(), passiveProgAccess.TheoryName(), "Boogie_Lang.PassificationML", boogieToVcTheoryName }; if (generateEndToEndLemma) { imports.Add("Boogie_Lang.PassificationEndToEnd"); } return(new Theory(theoryName, imports, passificationProofDecls)); }
/** * cases: * 1) is loop head block * 2) is back edge block * 3) successor is loop head block * * any combination is possible */ public static Theory CfgToDagProof( PhasesTheories phasesTheories, bool generateEndToEndLemma, Term vcAssm, CFGRepr beforeDagCfg, CFGRepr afterDagCfg, Block afterUniqueExit, BoogieMethodData beforeDagData, CfgToDagHintManager hintManager, IDictionary <Block, Block> beforeToAfter, IProgramAccessor beforeDagProgAccess, IProgramAccessor afterDagProgAccess, IVariableTranslationFactory varFactory) { var afterToBefore = beforeToAfter.InverseDict(); //track mapping from blocks to loops that the block is contained in and for which it is not the loop head IDictionary <Block, IList <Block> > blocksToLoops = new Dictionary <Block, IList <Block> >(); foreach (var afterBlock in afterDagCfg.GetBlocksBackwards()) { if (afterToBefore.TryGetValue(afterBlock, out var beforeBlock)) { var loops = new HashSet <Block>(); foreach (var bSuc in beforeDagCfg.GetSuccessorBlocks(beforeBlock)) { if (blocksToLoops.TryGetValue(bSuc, out var loopsSuc)) { //if successor inside of a loop L and the block is not the loop head of L, then the block is also inside L foreach (var loopSuc in loopsSuc) { if (!loopSuc.Equals(beforeBlock)) { loops.Add(loopSuc); } } } } /* a node is inside all loops for which it has an out-going backedge * if a node has a backedge to itself (i.e., it is also a loop head), then we do not add this loop */ if (hintManager.TryIsBackedgeNode(beforeBlock, out var backedgeLoops)) { foreach (var backedgeLoop in backedgeLoops) { if (beforeBlock != backedgeLoop) { loops.Add(backedgeLoop); } } } var loopsList = loops.ToList(); blocksToLoops.Add(beforeBlock, loopsList); } } var varContextName = "\\<Lambda>1"; var varContextAbbrev = new AbbreviationDecl( varContextName, new Tuple <IList <Term>, Term>(new List <Term>(), beforeDagProgAccess.VarContext()) ); var funContextWfName = "Wf_Fun"; var boogieContext = new BoogieContextIsa( IsaCommonTerms.TermIdentFromName("A"), IsaCommonTerms.TermIdentFromName("M"), IsaCommonTerms.TermIdentFromName(varContextName), IsaCommonTerms.TermIdentFromName("\\<Gamma>"), IsaCommonTerms.EmptyList); var lemmaManager = new CfgToDagLemmaManager( beforeDagProgAccess, afterDagProgAccess, boogieContext, afterDagCfg, funContextWfName, hintManager, blocksToLoops, beforeToAfter, beforeDagData, afterUniqueExit, varFactory); var lemmaNamer = new IsaUniqueNamer(); var outerDecls = new List <OuterDecl>(); outerDecls.Add(varContextAbbrev); outerDecls.Add(new DeclareDecl("Nat.One_nat_def[simp del]")); if (afterUniqueExit != null) { outerDecls.AddRange(lemmaManager.UnifiedExitLemma(GetCfgLemmaName(afterUniqueExit, lemmaNamer))); } foreach (var afterBlock in afterDagCfg.GetBlocksBackwards()) { if (afterToBefore.TryGetValue(afterBlock, out var beforeBlock)) { //if the node's only edge is a backedge, then an "assume false" will be added var singleCutEdge = hintManager.TryIsBackedgeNode(beforeBlock, out var _) && beforeDagCfg.NumOfSuccessors(beforeBlock) == 1; var(localLemmas, cfgLemma) = lemmaManager.BlockLemma( beforeBlock, afterBlock, beforeDagCfg.GetSuccessorBlocks(beforeBlock), block => GetLemmaName(block, lemmaNamer), block => GetCfgLemmaName(block, lemmaNamer), singleCutEdge ); outerDecls.AddRange(localLemmas); outerDecls.Add(cfgLemma); } else { //block was added as part of transformation if (afterBlock == afterDagCfg.entry) { //entry lemma handled elsewhere continue; } var afterBlockSuccessors = afterDagCfg.GetSuccessorBlocks(afterBlock); var afterBlockSuccessorsList = afterBlockSuccessors.ToList(); if (!afterBlockSuccessorsList.Any()) { //this must be the unique node if (afterUniqueExit == null) { throw new ProofGenUnexpectedStateException( "unique exit block added, but only exit block existed before cfg-to-dag"); } continue; } if (afterBlockSuccessorsList.Count != 1) { throw new ProofGenUnexpectedStateException( "Block added in CFG-to-DAG phase does not have a unique successor"); } var afterUniqueSuc = afterBlockSuccessorsList.First(); if (afterToBefore.TryGetValue(afterUniqueSuc, out var beforeUniqueSuc)) { hintManager.IsLoopHead(beforeUniqueSuc, out var hint); var lemma = lemmaManager.NewBlockLemma( GetCfgLemmaName(afterBlock, lemmaNamer), afterBlock, afterUniqueSuc, hint ); outerDecls.Add(lemma); } else if (hintManager.IsNewBackedgeBlock(afterBlock, out var loopHeadHint)) { if (afterDagCfg.GetSuccessorBlocks(afterUniqueSuc).Any()) { throw new ProofGenUnexpectedStateException( "New backedge node has successor that is not the exit node."); } //afterUniqueSuc is a successor to a backedge node for which all edges were eliminated var lemma = lemmaManager.NewBlockLemma( GetCfgLemmaName(afterBlock, lemmaNamer), afterBlock, null, loopHeadHint ); outerDecls.Add(lemma); } else { throw new ProofGenUnexpectedStateException( "CFG-to-DAG: Unique successor of added block cannot be mapped to original block"); } } } var entryLemma = lemmaManager.EntryLemma("entry_lemma", beforeDagCfg.entry, afterDagCfg.entry, b => GetCfgLemmaName(b, lemmaNamer)); outerDecls.Add(entryLemma); var absValType = new VarType("a"); var cfgToDagLemmasLocale = new LocaleDecl( "cfg_to_dag_lemmas", new ContextElem( new List <Tuple <TermIdent, TypeIsa> > { Tuple.Create((TermIdent)boogieContext.absValTyMap, IsaBoogieType.AbstractValueTyFunType(absValType)), Tuple.Create((TermIdent)boogieContext.funContext, IsaBoogieType.FunInterpType(absValType)) }, new List <Term> { IsaBoogieTerm.FunInterpWf(boogieContext.absValTyMap, beforeDagProgAccess.FunctionsDecl(), boogieContext.funContext) }, new List <string> { funContextWfName } ), outerDecls ); var theoryOuterDecls = new List <OuterDecl>(); theoryOuterDecls.Add(cfgToDagLemmasLocale); if (generateEndToEndLemma) { var endToEndManager = new CfgToDagEndToEnd(); var endToEndDecls = endToEndManager.EndToEndProof( cfgToDagLemmasLocale.Name + "." + entryLemma.Name, phasesTheories.EndToEndLemmaName(PhasesTheories.Phase.Passification, true), vcAssm, beforeDagProgAccess, beforeDagCfg ); theoryOuterDecls.AddRange(endToEndDecls); } return(new Theory( phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag), new List <string> { "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.BackedgeElim", "Boogie_Lang.TypingML", beforeDagProgAccess.TheoryName(), afterDagProgAccess.TheoryName(), phasesTheories.TheoryName(PhasesTheories.Phase.Passification), phasesTheories.TheoryName(PhasesTheories.Phase.Vc) }, theoryOuterDecls )); }