public PassificationLemmaManager( CFGRepr cfg, IDictionary <Block, Block> origToPassiveBlock, IProgramAccessor programAccessor, IProgramAccessor passiveProgramAccessor, Tuple <string, string> varContextNonPassivePassive, StateRelationData oldStateRelationData, PassiveRelationGen relationGen, IVariableTranslationFactory varTranslationFactory, IVariableTranslationFactory passiveTranslationFactory) { this.cfg = cfg; this.origToPassiveBlock = origToPassiveBlock; this.programAccessor = programAccessor; this.passiveProgramAccessor = passiveProgramAccessor; _oldStateRelationData = oldStateRelationData; _relationGen = relationGen; initState = IsaBoogieTerm.Normal(normalInitState); varTranslation = varTranslationFactory.CreateTranslation().VarTranslation; passiveVarTranslation = passiveTranslationFactory.CreateTranslation().VarTranslation; //separate unique namer for function interpretations (since they already have a name in uniqueNamer): possible clashes boogieContext = new BoogieContextIsa( IsaCommonTerms.TermIdentFromName("A"), IsaCommonTerms.TermIdentFromName("M"), IsaCommonTerms.TermIdentFromName(varContextNonPassivePassive.Item1), IsaCommonTerms.TermIdentFromName("\\<Gamma>"), IsaCommonTerms.TermIdentFromName("\\<Omega>") ); passiveVarContext = IsaCommonTerms.TermIdentFromName(varContextNonPassivePassive.Item2); }
public override Type VisitBasicType(BasicType node) { if (node.IsBool) { if (constructVal) { ReturnResult(IsaBoogieTerm.BoolVal(arg)); } else { ReturnResult(IsaBoogieTerm.ConvertValToBool(arg)); } } else if (node.IsInt) { if (constructVal) { ReturnResult(IsaBoogieTerm.IntVal(arg)); } else { ReturnResult(IsaBoogieTerm.ConvertValToInt(arg)); } } else { throw new NotImplementedException(); } return(node); }
public VcPhaseLemmaManager(VCInstantiation <Block> vcinst, BoogieMethodData methodData, IEnumerable <Function> vcFunctions, IsaBlockInfo isaBlockInfo, IVariableTranslationFactory variableFactory) { this.vcinst = vcinst; this.methodData = methodData; programVariables = methodData.AllVariables(); initState = IsaBoogieTerm.Normal(normalInitState); this.isaBlockInfo = isaBlockInfo; this.variableFactory = variableFactory; boogieContext = new BoogieContextIsa( IsaCommonTerms.TermIdentFromName("A"), IsaCommonTerms.TermIdentFromName("M"), IsaCommonTerms.TermIdentFromName("\\<Lambda>"), IsaCommonTerms.TermIdentFromName("\\<Gamma>"), IsaCommonTerms.TermIdentFromName("\\<Omega>") ); var typeDeclTranslation = new ConcreteTypeDeclTranslation(boogieContext); declToVCMapping = LemmaHelper.DeclToTerm( ((IEnumerable <NamedDeclaration>)methodData.Functions).Union(programVariables), vcFunctions, typeDeclTranslation, uniqueNamer); //separate unique namer for function interpretations (since they already have a name in uniqueNamer): possible clashes funToInterpMapping = LemmaHelper.FunToTerm(methodData.Functions, new IsaUniqueNamer()); assmManager = new AssumptionManager(methodData.Functions, programVariables, variableFactory); }
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)); }
public static Term BinderStateEmpty(Term normalState) { return(TermBinary.Eq( IsaBoogieTerm.BinderState(normalState), IsaCommonTerms.EmptyMap )); }
// TODO: adjust clients so don't require paramsAndLocals public static Term LocalStateAssumption(BoogieContextIsa boogieContext, Term paramsAndLocals, Term normalState) { return (IsaBoogieTerm.StateWf( boogieContext.absValTyMap, boogieContext.rtypeEnv, paramsAndLocals, IsaBoogieTerm.LocalState(normalState))); }
// TODO: adjust clients so don't require constsAndGlobals public static Term GlobalStateAssumption(BoogieContextIsa boogieContext, Term constsAndGlobals, Term normalState) { return (IsaBoogieTerm.StateWf( boogieContext.absValTyMap, boogieContext.rtypeEnv, constsAndGlobals, IsaBoogieTerm.GlobalState(normalState))); }
public void AddFunctionMembershipLemmas(IEnumerable <Function> functions) { AddNamedDeclsMembershipLemmas(functions, IsaCommonTerms.TermIdentFromName(isaProgramRepr.GlobalProgramRepr.funcsDeclDef), new[] { isaProgramRepr.GlobalProgramRepr.funcsDeclDef + "_def" }, d => new StringConst(d.Name), d => IsaBoogieTerm.FunDecl((Function)d, factory, false), false ); }
public static Term ClosednessAssumption(Term absValTyMap) { Identifier boundVar = new SimpleIdentifier("v"); return(TermQuantifier.MetaAll(new List <Identifier> { boundVar }, null, IsaBoogieTerm.IsClosedType(IsaBoogieTerm.TypeToVal(absValTyMap, new TermIdent(boundVar))) )); }
public static Term VariableTypeAssumption( Variable v, Term vcVar, TypeIsaVisitor typeIsaVisitor, Term absValTyMap) { var left = IsaBoogieTerm.TypeToVal(absValTyMap, vcVar); var right = typeIsaVisitor.Translate(v.TypedIdent.Type); return(TermBinary.Eq(left, right)); }
public static Term AxiomAssumption(BoogieContextIsa boogieContext, IProgramAccessor programAccessor, Term normalState) { return (IsaBoogieTerm.AxiomAssm( boogieContext.absValTyMap, boogieContext.funContext, IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()), normalState, programAccessor.AxiomsDecl() )); }
//desugar into single havoc commands private IList <Term> TranslateHavocCmd(HavocCmd node) { var varResults = node.Vars.Select(var => TranslateIdentifierExpr(var)); IList <Term> results = new List <Term>(); foreach (var v in varResults) { results.Add(IsaBoogieTerm.Havoc(v)); } return(results); }
public static Term LocalStateVariableAssumption(Variable v, Term varContext, Term normalState, Term vcVar, IVariableTranslation <Variable> varTranslation) { if (varTranslation.TryTranslateVariableId(v, out var varId, out var isBoundVar) && !isBoundVar) { var left = IsaBoogieTerm.LookupVar(varContext, normalState, varId); var right = IsaCommonTerms.SomeOption(pureToBoogieValConverter.ConvertToBoogieVal(v.TypedIdent.Type, vcVar)); return(new TermBinary(left, right, TermBinary.BinaryOpCode.Eq)); } throw new ProofGenUnexpectedStateException(typeof(LemmaHelper), "Can't retrieve variable id"); }
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 override Type VisitBasicType(BasicType node) { if (node.IsBool) { ReturnResult(v => IsaBoogieTerm.BoolVal(v)); } else if (node.IsInt) { ReturnResult(v => IsaBoogieTerm.IntVal(v)); } else { throw new NotImplementedException(); } return(node); }
private static Term ConclusionBlock( IEnumerable <Block> b_successors, Term normalInitState, Term finalState, IDictionary <NamedDeclaration, Term> declToVCMapping, VCInstantiation <Block> vcinst, bool useMagicFinalState = false) { if (useMagicFinalState) { return(new TermBinary(finalState, IsaBoogieTerm.Magic(), TermBinary.BinaryOpCode.Eq)); } Term nonFailureConclusion = new TermBinary(finalState, IsaBoogieTerm.Failure(), TermBinary.BinaryOpCode.Neq); var normalFinalState = IsaCommonTerms.TermIdentFromName("n_s'"); Term ifNormalConclusionLhs = new TermBinary(finalState, IsaBoogieTerm.Normal(normalFinalState), TermBinary.BinaryOpCode.Eq); Term ifNormalConclusionRhs1 = new TermBinary(normalFinalState, normalInitState, TermBinary.BinaryOpCode.Eq); var ifNormalConclusionRhs = !b_successors.Any() ? ifNormalConclusionRhs1 : new TermBinary( ifNormalConclusionRhs1, LemmaHelper.ConjunctionOfSuccessorBlocks(b_successors, declToVCMapping, vcinst), TermBinary.BinaryOpCode.And); Term ifNormalConclusion = new TermQuantifier( TermQuantifier.QuantifierKind.ALL, new List <Identifier> { normalFinalState.Id }, new TermBinary( ifNormalConclusionLhs, ifNormalConclusionRhs, TermBinary.BinaryOpCode.Implies) ); return(new TermBinary(nonFailureConclusion, ifNormalConclusion, TermBinary.BinaryOpCode.And)); }
public static Term NonEmptyTypesAssumption(Term absValTyMap) { Identifier bvType = new SimpleIdentifier("t"); Term bvTypeTerm = new TermIdent(bvType); Identifier bvValue = new SimpleIdentifier("v"); Term bvValueTerm = new TermIdent(bvValue); return(TermQuantifier.MetaAll(new List <Identifier> { bvType }, null, TermBinary.MetaImplies(IsaBoogieTerm.IsClosedType(bvTypeTerm), TermQuantifier.Exists(new List <Identifier> { bvValue }, null, TermBinary.Eq(IsaBoogieTerm.TypeToVal(absValTyMap, bvValueTerm), bvTypeTerm) )))); }
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 static Term FunctionVcCorresAssm( Function f, IDictionary <Function, TermIdent> funInterpMapping, IDictionary <NamedDeclaration, Term> declToVCMapping, BoogieContextIsa boogieContext ) { var converter = new PureToBoogieValConverter(); //TODO: unique naming scheme var boundParamVars = GetNames("farg", f.InParams.Count); TypeUtil.SplitTypeParams(f.TypeParameters, f.InParams.Select(v => v.TypedIdent.Type), out var explicitTypeVars, out var implicitTypeVars); var boundTypeVars = GetNames("targ", f.TypeParameters.Count); IDictionary <TypeVariable, Term> substitution = new Dictionary <TypeVariable, Term>(); var i = 0; foreach (var tv in f.TypeParameters) { substitution.Add(tv, new TermIdent(boundTypeVars[i])); i++; } var varSubstitution = new SimpleVarSubstitution <TypeVariable>(substitution); var typeIsaVisitor = new TypeIsaVisitor(varSubstitution); IEnumerable <Term> valueArgConstraints = f.InParams .Select((v, idx) => !TypeUtil.IsPrimitive(v.TypedIdent.Type) ? TermBinary.Eq( IsaBoogieTerm.TypeToVal(boogieContext.absValTyMap, new TermIdent(boundParamVars[idx])), typeIsaVisitor.Translate(v.TypedIdent.Type)) : null) .Where(t => t != null); var boogieFunTyArgs = boundTypeVars.Select(id => (Term) new TermIdent(id)).ToList(); var vcFunTyArgs = new List <Term>(); f.TypeParameters.ZipDo(boogieFunTyArgs, (tv, tvTerm) => { if (explicitTypeVars.Contains(tv)) { vcFunTyArgs.Add(IsaBoogieVC.TyToClosed(tvTerm)); } }); var boogieFunValArgs = f.InParams.Select( (v, idx) => converter.ConvertToBoogieVal(v.TypedIdent.Type, new TermIdent(boundParamVars[idx])) ).ToList(); Term left = new TermApp(funInterpMapping[f], new List <Term> { new TermList(boogieFunTyArgs), new TermList(boogieFunValArgs) }); Term vcFunApp = new TermApp(declToVCMapping[f], vcFunTyArgs.Union( boundParamVars.Select(bv => (Term) new TermIdent(bv)).ToList() ).ToList()); var outputType = f.OutParams.First().TypedIdent.Type; var right = IsaCommonTerms.SomeOption( converter.ConvertToBoogieVal(outputType, vcFunApp) ); Term equation = TermBinary.Eq(left, right); Term conclusion; if (!TypeUtil.IsPrimitive(outputType)) { //if type is not primitive, then the type information is not yet included conclusion = TermBinary.And(equation, TermBinary.Eq( IsaBoogieTerm.TypeToVal(boogieContext.absValTyMap, vcFunApp), typeIsaVisitor.Translate(outputType) )); } else { conclusion = equation; } if (valueArgConstraints.Any()) { conclusion = TermBinary.MetaImplies(valueArgConstraints.Aggregate((t1, t2) => TermBinary.And(t2, t1)), conclusion); } if (boogieFunTyArgs.Any()) { var closednessAssms = boogieFunTyArgs.Select(t1 => IsaBoogieTerm.IsClosedType(t1)) .Aggregate((t1, t2) => TermBinary.And(t2, t1)); conclusion = TermBinary.MetaImplies(closednessAssms, conclusion); } if (boundParamVars.Any()) { return(new TermQuantifier(TermQuantifier.QuantifierKind.META_ALL, boundParamVars.Union(boundTypeVars).ToList(), conclusion)); } return(conclusion); }
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 Term Bool2U(Function func) { return(IsaBoogieTerm.BoolValConstr()); }
public static Term OldGlobalStateAssumption(Term normalState) { return(TermBinary.Eq(IsaBoogieTerm.GlobalState(normalState), IsaBoogieTerm.OldGlobalState(normalState))); }
/** * 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 )); }
public override Term Int2U(Function func) { return(IsaBoogieTerm.IntValConstr()); }
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))); }