/// <summary> /// Return lookup lemmas for each element in the old relation as well as the definition of the old relation, which /// is defined via an association list /// </summary> private static StateRelationData OldRelation( ISet <Variable> oldGlobalVars, IVariableTranslation <Variable> variableTranslation, out IList <OuterDecl> oldRelDecls) { //assume that passive version representing old variable of "g" is "g" itself var oldRelTuples = new List <Term>(); var varList = new List <Variable>(); var varToLookupLemma = new Dictionary <Variable, LemmaDecl>(); var uniqueNamer = new IsaUniqueNamer(); foreach (var v in oldGlobalVars) { if (variableTranslation.TryTranslateVariableId(v, out var varTermId, out _)) { oldRelTuples.Add(new TermTuple(varTermId, IsaCommonTerms.Inl(varTermId))); var lemma = new LemmaDecl( "lookup_old_rel" + uniqueNamer.GetName(v, v.Name), TermBinary.Eq(new TermApp(oldRel, varTermId), IsaCommonTerms.SomeOption(IsaCommonTerms.Inl(varTermId))), new Proof(new List <string> { "unfolding " + oldRelListName + "_def " + oldRelName + "_def", "by simp" }) ); varToLookupLemma.Add(v, lemma); varList.Add(v); }
public static void SetTypeEraserFactory(TypePremiseEraserFactory factory) { if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) { return; } typePremiseEraserFactory = factory; var uniqueNamer = new IsaUniqueNamer(); /* Hack: try to make sure unique namer uses names for Boogie functions and Boogie variables that are different * from the default name otherwise it clashes with the functions potentially fixed in the context of a locale */ foreach (var fun in boogieGlobalData.Functions) { uniqueNamer.GetName(fun.Name, "o123_" + fun.Name); } foreach (var variable in finalProgData.AllVariables()) { uniqueNamer.GetName(variable.Name, "o123_" + variable.Name); } //Hack: translate vc variable based on name, to ensure that applying erasure multiple times shares the same variables var translator = VCExprToIsaTranslator.CreateNameBasedTranslator(uniqueNamer); translator.SetFunctionNamer(uniqueNamer); translator.SetTryInstantiatingFunctions(true); vcHintManager = new VCHintManager(new VcRewriteLemmaGen(factory, translator)); }
public static IDictionary <NamedDeclaration, Term> DeclToTerm( IEnumerable <NamedDeclaration> decls, IEnumerable <Function> vcTypeDecls, VCTypeDeclTranslation typeDeclTranslation, IsaUniqueNamer namer) { var dict = new Dictionary <NamedDeclaration, Term>(); foreach (var decl in decls) { dict.Add(decl, IsaCommonTerms.TermIdentFromName(namer.GetName(decl, "vc_" + decl.Name))); } foreach (var f in vcTypeDecls) { if (typeDeclTranslation.TryTranslateTypeDecl(f, out var result)) { dict.Add(f, result); } else { throw new ProofGenUnexpectedStateException(typeof(LemmaHelper), "Could not find vc function instantiation"); } } return(dict); }
public VCExprOpIsaVisitor(IsaUniqueNamer functionNamer) { _uniqueNamer = functionNamer; var boogieContext = new BoogieContextIsa( IsaCommonTerms.TermIdentFromName("A"), IsaCommonTerms.TermIdentFromName("M"), IsaCommonTerms.TermIdentFromName("\\<Lambda>"), IsaCommonTerms.TermIdentFromName("\\<Gamma>"), IsaCommonTerms.TermIdentFromName("\\<Omega>")); _concreteTypeTranslation = new ConcreteTypeDeclTranslation(boogieContext); }
private static IList <Tuple <TermIdent, TypeIsa> > GetVarsInVC(IEnumerable <Function> functions, IsaUniqueNamer uniqueNamer) { var pureTyIsaTransformer = new PureTyIsaTransformer(); var result = new List <Tuple <TermIdent, TypeIsa> >(); foreach (var f in functions) { var funType = pureTyIsaTransformer.Translate(f); result.Add(Tuple.Create(IsaCommonTerms.TermIdentFromName(uniqueNamer.GetName(f, f.Name)), funType)); } return(result); }
private static IDictionary <Block, OuterDecl> GenerateCfgLemmas( CFGRepr afterPassificationCfg, CFGRepr finalCfg, IDictionary <Block, Block> afterPassiveToFinalBlock, HashSet <Block> reachableBlocks, IDictionary <Block, IList <OuterDecl> > lemmaDecls, VcPhaseLemmaManager vcPhaseLemmaManager, Term cfgTerm, IsaUniqueNamer lemmaNamer) { var blockToLemmaDecls = new Dictionary <Block, OuterDecl>(); foreach (var bAfterPassive in afterPassificationCfg.GetBlocksBackwards()) { IEnumerable <Block> finalCfgSuccessors; var isContainedInFinalCfg = afterPassiveToFinalBlock.TryGetValue(bAfterPassive, out var bFinal); if (!isContainedInFinalCfg) { if (reachableBlocks.Contains(bAfterPassive)) { finalCfgSuccessors = GetNonEmptyReachableSuccessors(bAfterPassive, afterPassificationCfg, finalCfg, afterPassiveToFinalBlock).Select(b => afterPassiveToFinalBlock[b]); } else { continue; } } else { finalCfgSuccessors = finalCfg.GetSuccessorBlocks(bFinal); } var lemma = vcPhaseLemmaManager.GenerateCfgLemma( bAfterPassive, bFinal, isContainedInFinalCfg, afterPassificationCfg.GetSuccessorBlocks(bAfterPassive), finalCfgSuccessors, cfgTerm, b => "cfg_" + lemmaNamer.GetName(b, b.Label), (LemmaDecl)lemmaDecls[bAfterPassive].Last()); blockToLemmaDecls.Add(bAfterPassive, lemma); } return(blockToLemmaDecls); }
/// <param name="uniqueNamer">namer to be used for vc variables</param> /// <param name="successorToVC"></param> /// <param name="blockToActiveVars"></param> /// <param name="useNamesOfVarsForTranslation"> /// if set to true, then <paramref name="uniqueNamer" /> will be applied /// to the name of a vc variable instead of the object, also <see cref="CreateNameBasedTranslator" /> /// </param> public VCExprToIsaTranslator( IsaUniqueNamer uniqueNamer, IDictionary <Block, DefDecl> successorToVC, IDictionary <Block, IList <VCExprVar> > blockToActiveVars, bool useNamesOfVarsForTranslation = false) { this.uniqueNamer = uniqueNamer; this.useNamesOfVarsForTranslation = useNamesOfVarsForTranslation; this.successorToVC = successorToVC; this.blockToActiveVars = blockToActiveVars; criticalOps = new HashSet <VCExprOp> { VCExpressionGenerator.NotOp, VCExpressionGenerator.ImpliesOp, VCExpressionGenerator.AndOp, VCExpressionGenerator.OrOp }; }
public static IList <Tuple <TermIdent, TypeIsa> > GlobalFixedVariables( BoogieContextIsa boogieContext, IEnumerable <Function> functions, IEnumerable <Variable> variables, TermIdent normalInitState, IDictionary <Function, TermIdent> funToInterpMapping, IsaUniqueNamer uniqueNamer) { var absValType = new VarType("a"); var pureTyIsaTransformer = LemmaHelper.ConretePureTyIsaTransformer(absValType); var result = new List <Tuple <TermIdent, TypeIsa> > { Tuple.Create((TermIdent)boogieContext.absValTyMap, IsaBoogieType.AbstractValueTyFunType(absValType)), Tuple.Create((TermIdent)boogieContext.varContext, IsaBoogieType.VarContextType()), Tuple.Create((TermIdent)boogieContext.funContext, IsaBoogieType.FunInterpType(absValType)), Tuple.Create(normalInitState, IsaBoogieType.NormalStateType(absValType)) }; foreach (var kv in funToInterpMapping) { result.Add(Tuple.Create(kv.Value, IsaBoogieType.BoogieFuncInterpType(absValType))); var boogieFun = kv.Key; //get untyped version, maybe should precompute this somewhere and re-use or get the data from the VC TypeUtil.SplitTypeParams(boogieFun.TypeParameters, boogieFun.InParams.Select(v => v.TypedIdent.Type), out var explicitTypeVars, out _); var typeIsa = pureTyIsaTransformer.Translate(new Function(null, boogieFun.Name, explicitTypeVars, boogieFun.InParams, boogieFun.OutParams[0])); result.Add(Tuple.Create( IsaCommonTerms.TermIdentFromName(uniqueNamer.GetName(boogieFun, boogieFun.Name)), typeIsa)); } foreach (var v in variables) { var typeIsa = pureTyIsaTransformer.Translate(v); result.Add(Tuple.Create(IsaCommonTerms.TermIdentFromName(uniqueNamer.GetName(v, v.Name)), typeIsa)); } return(result); }
public VCBlockToIsaTranslator(IsaUniqueNamer uniqueNamer) { this.uniqueNamer = uniqueNamer; }
public void setFunctionNamer(IsaUniqueNamer functionNamer) { _uniqueNamer = functionNamer; }
private static string GetCfgLemmaName(Block b, IsaUniqueNamer namer) { return("cfg_" + namer.GetName(b, "block_" + b.Label)); }
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)); }
//assume that block identities in the two CFGs are the same (only edges may be different) private static IDictionary <Block, IList <OuterDecl> > GenerateVCLemmas( CFGRepr afterPassificationCfg, CFGRepr finalCfg, IDictionary <Block, Block> afterPassiveToFinalBlock, IDictionary <Block, Block> afterPassiveToOrigBlock, HashSet <Block> reachableBlocks, VcPhaseLemmaManager vcPhaseLemmaManager, VCHintManager vcHintManager, IsaUniqueNamer lemmaNamer) { var blockToLemmaDecls = new Dictionary <Block, IList <OuterDecl> >(); foreach (var bAfterPassive in afterPassificationCfg.GetBlocksBackwards()) { var result = new List <OuterDecl>(); if (afterPassiveToFinalBlock.TryGetValue(bAfterPassive, out var bFinal)) { string vcHintsName = null; if (vcHintManager.TryGetHints(afterPassiveToOrigBlock[bAfterPassive], out var hints, out var requiredDecls)) { //FIXME potential val name clash vcHintsName = GetLemmaName(bAfterPassive, lemmaNamer) + "_hints"; var code = MLUtil.DefineVal(vcHintsName, MLUtil.MLList(hints)); //required declarations must be added first result.AddRange(requiredDecls); result.Add(new MLDecl(code)); } result.Add(vcPhaseLemmaManager.GenerateBlockLemma( bAfterPassive, bFinal, finalCfg.GetSuccessorBlocks(bFinal), GetLemmaName(bFinal, lemmaNamer), vcHintsName)); //do not use identity of final CFG block to be consistent with other branches blockToLemmaDecls.Add(bAfterPassive, result); } else if (reachableBlocks.Contains(bAfterPassive)) { //block was removed after peephole but is reachable before peephole if (bAfterPassive.Cmds.Count == 0) { //find the successors of b in the final cfg (i.e., the first non-empty reachable blocks) var nonEmptyReachableSuccessors = GetNonEmptyReachableSuccessors(bAfterPassive, afterPassificationCfg, finalCfg, afterPassiveToFinalBlock); //add lemma var decls = new List <OuterDecl> { vcPhaseLemmaManager.GenerateEmptyBlockLemma( bAfterPassive, nonEmptyReachableSuccessors.Select(b => afterPassiveToFinalBlock[b]), GetLemmaName(bAfterPassive, lemmaNamer)) }; blockToLemmaDecls.Add(bAfterPassive, decls); } else { throw new ProofGenUnexpectedStateException( "Non-empty reachable block removed during peep-hole"); } } } return(blockToLemmaDecls); }
/** * 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 static IDictionary <Function, TermIdent> FunToTerm(IEnumerable <Function> funcs, IsaUniqueNamer namer) { var dict = new Dictionary <Function, TermIdent>(); foreach (var fun in funcs) { dict.Add(fun, IsaCommonTerms.TermIdentFromName(namer.GetName(fun, fun.Name))); } return(dict); }
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 static Theory ProgramToVcProof( string theoryName, bool generateEndToEndProof, CFGRepr finalCfg, CFGRepr afterPassificationCfg, IDictionary <Block, Block> afterPassiveToFinalBlock, IDictionary <Block, Block> afterPassiveToOrigBlock, IProgramAccessor passiveProgAccess, IProgramAccessor beforePassiveProgAccess, BoogieMethodData methodData, ProgramVcProofData vcProofData, IVariableTranslationFactory varFactory, TypePremiseEraserFactory eraserFactory, VCExpressionGenerator gen, out Term vcAssm, out LemmaDecl endToEndLemma) { var lemmaNamer = new IsaUniqueNamer(); var passiveLemmaManager = new VcPhaseLemmaManager( vcProofData.VcBoogieInfo.VcInst, methodData, vcProofData.VcFunctions, passiveProgAccess.BlockInfo(), varFactory); var afterPassiveReachableBlocks = ReachableBlocks(afterPassificationCfg); var finalProgramLemmas = GenerateVCLemmas(afterPassificationCfg, finalCfg, afterPassiveToFinalBlock, afterPassiveToOrigBlock, afterPassiveReachableBlocks, passiveLemmaManager, vcProofData.VcHintManager, lemmaNamer); var cfgProgramLemmas = GenerateCfgLemmas(afterPassificationCfg, finalCfg, afterPassiveToFinalBlock, afterPassiveReachableBlocks, finalProgramLemmas, passiveLemmaManager, passiveProgAccess.CfgDecl(), lemmaNamer); var afterPassificationDecls = new List <OuterDecl>(); foreach (var v in finalProgramLemmas.Values) { afterPassificationDecls.AddRange(v); } afterPassificationDecls.AddRange(cfgProgramLemmas.Values); var afterPassificationLocale = GenerateLocale("passification", passiveLemmaManager, afterPassificationDecls); var passiveOuterDecls = new List <OuterDecl> { vcProofData.VcLocale }; passiveOuterDecls.Add(afterPassificationLocale); //generate axiom var axiomUniqueNamer = new IsaUniqueNamer(); var axId = 0; var axiomToLemma = new Dictionary <Axiom, OuterDecl>(); var vcRewriteLemmaGen = new VcRewriteLemmaGen(eraserFactory, VCExprToIsaTranslator.CreateNameBasedTranslator(new IsaUniqueNamer())); var vcAxiomLemmaManager = new VcAxiomLemmaManager( vcProofData.VcBoogieInfo.VcInstAxiom, methodData, vcProofData.VcFunctions, vcRewriteLemmaGen, varFactory); var axiomLocaleRequiredDecls = new List <OuterDecl>(); foreach (var axiom in vcProofData.VcBoogieInfo.VcAxiomsInfo) { if (axiom is VcBoogieAxiomInfo vcBoogieAxiom) { var axiomVcLemma = vcAxiomLemmaManager.AxiomVcLemma( axiomUniqueNamer.GetName(axiom, "axiom_vc_" + axId), vcBoogieAxiom.Axiom, vcBoogieAxiom.Expr, out var requiredDecls); axiomToLemma.Add(vcBoogieAxiom.Axiom, axiomVcLemma); axiomLocaleRequiredDecls.AddRange(requiredDecls); } } /* we add the required declarations for the axiom locale to the outer theory, since the axiom locale fixes variables that could clash * with the declarations */ passiveOuterDecls.AddRange(axiomLocaleRequiredDecls); var axiomLocale = GenerateLocale("axioms", vcAxiomLemmaManager, axiomToLemma.Values.ToList()); passiveOuterDecls.Add(axiomLocale); if (generateEndToEndProof) { var endToEnd = new EndToEndVCProof( methodData, passiveProgAccess, vcProofData.VcFunctions, vcProofData.VcBoogieInfo, afterPassificationCfg, finalCfg, afterPassificationLocale.Name + "." + cfgProgramLemmas[afterPassificationCfg.entry].Name, axiomLocale.Name, ax => axiomLocale.Name + "." + axiomToLemma[ax].Name, varFactory, vcProofData.VcTranslator, eraserFactory, gen); passiveOuterDecls.AddRange(endToEnd.GenerateProof(out vcAssm, out endToEndLemma)); } else { vcAssm = null; endToEndLemma = null; } return (new Theory(theoryName, new List <string> { "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.VCHints", "Boogie_Lang.VCPhaseML", passiveProgAccess.TheoryName(), beforePassiveProgAccess.TheoryName() }, passiveOuterDecls)); }
private static string GetLemmaName(Block b, IsaUniqueNamer uniqueNamer) { return(uniqueNamer.GetName(b, "block_" + b.Label)); }
public static Term VariableAssumptionExplicit(Variable v, Term state, Term rhs, IsaUniqueNamer uniqueNamer) { Term left = new TermApp(state, new StringConst(v.Name)); return(new TermBinary(left, rhs, TermBinary.BinaryOpCode.Eq)); }
public VCExprToIsaTranslator(IsaUniqueNamer uniqueNamer) : this(uniqueNamer, new Dictionary <Block, DefDecl>(), new Dictionary <Block, IList <VCExprVar> >()) { }
/// <summary> /// Generate all proofs for the current procedure. /// </summary> /// <param name="vc">WP of the procedure body</param> /// <param name="vcAxioms">VC assumptions for the Boogie axioms</param> /// <param name="typeAxioms">VC assumptions for the Boogie type encoding</param> /// <param name="typeAxiomInfo">Hints about the type encoding</param> /// <param name="gen"></param> /// <param name="translator"></param> /// <param name="axiomBuilder"></param> /// <exception cref="ArgumentException"> /// axiom builder must be null iff types are not erased (since no polymorphism in vc), otherwise exception is /// thrown /// </exception> public static void VCGenerateAllProofs( VCExpr vc, VCExpr vcAxioms, VCExpr typeAxioms, List <VCAxiomInfo> typeAxiomInfo, VCExpressionGenerator gen, Boogie2VCExprTranslator translator, TypeAxiomBuilderPremisses axiomBuilder) { var uniqueNamer = new IsaUniqueNamer(); var theories = new List <Theory>(); if (axiomBuilder == null && typeAxioms != null) { throw new ArgumentException("type axioms can only be null if axiom builder is null"); } /* Since in the proofs calls are desugared, there can be more variables in "beforePassiveData". If only * the progam should be generaed, then these variables should be ignored. */ var mainData = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? beforeDagData : beforePassiveData; var fixedVarTranslation2 = new DeBruijnFixedVarTranslation(mainData); var fixedTyVarTranslation2 = new DeBruijnFixedTVarTranslation(mainData); var varTranslationFactory2 = new DeBruijnVarFactory(fixedVarTranslation2, fixedTyVarTranslation2, boogieGlobalData); #region before cfg to dag program var beforeCfgToDagTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_cfg_to_dag_prog"); //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) var specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; var beforeCfgToDagConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, false, false, false, true, specsConfig, true); var beforeCfgToDagProgAccess = new IsaProgramGenerator().GetIsaProgram( beforeCfgToDagTheoryName, afterPassificationImpl.Name, mainData, beforeCfgToDagConfig, varTranslationFactory2, beforeDagCfg, out var programDeclsBeforeCfgToDag, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name, beforeCfgToDagProgAccess); var beforeCfgToDagProgTheory = new Theory(beforeCfgToDagTheoryName, new List <string> { "Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", "\"../" + globalDataProgAccess.TheoryName() + "\"" }, programDeclsBeforeCfgToDag); theories.Add(beforeCfgToDagProgTheory); #endregion if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) { StoreResult("program_" + afterPassificationImpl.Proc.Name, theories); return; } #region before passive program var beforePassiveProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_passive_prog"); var beforePassiveConfig = new IsaProgramGeneratorConfig(beforeCfgToDagProgAccess, false, false, false, false, SpecsConfig.None, false); var beforePassiveProgAccess = new IsaProgramGenerator().GetIsaProgram(beforePassiveProgTheoryName, afterPassificationImpl.Name, mainData, beforePassiveConfig, varTranslationFactory2, beforePassificationCfg, out var programDeclsBeforePassive, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); #endregion var vcAllAxioms = AxiomHandler.AxiomInfo( axiomBuilder != null, boogieGlobalData.Axioms, vcAxioms, typeAxioms, typeAxiomInfo, out var allAxiomsInfo); var vcLocale = VCToIsaInterface.ConvertVC( "vc", vc, vcAllAxioms, new StandardActiveDecl(), translator, axiomBuilder, finalProgData, afterUnreachablePruningCfg, out var vcinst, out var vcinstAxiom, out var vcTranslator, out var vcFunctions); //use global version map for translation var fixedVarTranslation = new SimpleFixedVarTranslation(globalVersionMap); var fixedTyVarTranslation = new DeBruijnFixedTVarTranslation(finalProgData); varTranslationFactory = new DeBruijnVarFactory(fixedVarTranslation, fixedTyVarTranslation, boogieGlobalData); var finalProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_passive_prog"); var passiveProgConfig = new IsaProgramGeneratorConfig(beforePassiveProgAccess, false, false, false, true, SpecsConfig.None, false); var passiveProgAccess = new IsaProgramGenerator().GetIsaProgram(finalProgTheoryName, afterPassificationImpl.Name, finalProgData, passiveProgConfig, varTranslationFactory, //we use the CFG before the peep-hole transformations, so that we can directly use the VC to program proof in the passification phase afterPassificationCfg, out var programDecls, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); var finalProgTheory = new Theory(finalProgTheoryName, new List <string> { "Boogie_Lang.Semantics", "Boogie_Lang.Util", beforePassiveProgAccess.TheoryName() }, programDecls); theories.Add(finalProgTheory); var vcBoogieInfo = new VcBoogieInfo(vcinst, vcinstAxiom, vcAllAxioms, allAxiomsInfo); var vcProofData = new ProgramVcProofData( vcFunctions, vcBoogieInfo, vcHintManager, vcLocale, vcTranslator ); var phasesTheories = new PhasesTheories(afterPassificationImpl.Name); var theoryPassive = VcPhaseManager.ProgramToVcProof( phasesTheories.TheoryName(PhasesTheories.Phase.Vc), _proofGenConfig.GenerateVcE2E, afterUnreachablePruningCfg, afterPassificationCfg, afterPassificationToAfterUnreachableBlock, afterPassificationToOrigBlock, passiveProgAccess, beforePassiveProgAccess, finalProgData, vcProofData, varTranslationFactory, typePremiseEraserFactory, gen, out var vcAssm, out var endToEndLemma ); theories.Add(theoryPassive); #region before passive var passificationProgTheory = new Theory(beforePassiveProgTheoryName, new List <string> { "Boogie_Lang.Semantics", "Boogie_Lang.Util", beforeCfgToDagTheoryName }, programDeclsBeforePassive); theories.Add(passificationProgTheory); /* * Console.WriteLine("Passive prog mapping: " + fixedVarTranslation.OutputMapping()); * Console.WriteLine("Before passive prog mapping: " + fixedVarTranslation2.OutputMapping()); */ var passificationProofTheory = PassificationManager.PassificationProof( phasesTheories.TheoryName(PhasesTheories.Phase.Passification), theoryPassive.TheoryName, _proofGenConfig.GeneratePassifE2E, endToEndLemma, vcAssm, beforePassificationCfg, beforePassiveToAfterPassiveBlock, passiveRelationGen, beforePassiveProgAccess, passiveProgAccess, mainData, varTranslationFactory2, varTranslationFactory ); theories.Add(passificationProofTheory); #endregion #region cfg to dag var uniqueExitBlock = uniqueExitBlockOrig != null ? beforePassiveOrigBlock.First(kv => kv.Value == uniqueExitBlockOrig).Key : null; var cfgToDagProofTheory = CfgToDagManager.CfgToDagProof( phasesTheories, _proofGenConfig.GenerateCfgDagE2E, vcAssm, beforeDagCfg, beforePassificationCfg, uniqueExitBlock, beforeDagData, cfgToDagHintManager, beforeDagAfterDagBlock, beforeCfgToDagProgAccess, beforePassiveProgAccess, varTranslationFactory2); theories.Add(cfgToDagProofTheory); #endregion StoreResult(afterPassificationImpl.Proc.Name, theories); }
public GenericTypeDeclTranslation(IsaUniqueNamer uniqueNamer) { this.uniqueNamer = uniqueNamer; }