//if blockToNewVars is non-null, then the mapped variables are universally quantified for the corresponding block definition public IDictionary <Block, DefDecl> IsaDefsFromVC(IDictionary <Block, VCExpr> blockToVC, IDictionary <Block, IList <VCExprVar> > blockToActiveVars, CFGRepr cfg, IDictionary <Block, IList <VCExprVar> > blockToNewVars = null) { Contract.Ensures(Contract.Result <IDictionary <Block, DefDecl> >().Count == cfg.NumOfBlocks()); IDictionary <Block, DefDecl> blockToDefVC = new Dictionary <Block, DefDecl>(); var vcExprIsaVisitor = new VCExprToIsaTranslator(uniqueNamer, blockToDefVC, blockToActiveVars); foreach (var block in cfg.GetBlocksBackwards()) { // might be more efficient to hand over this: // IEnumerable<Tuple<Block, DefDecl>> successorDefs = cfg.outgoingBlocks[block].Select(b => new Tuple<Block, DefDecl>(b, blockToDefVC[b])); var term = vcExprIsaVisitor.Translate(blockToVC[block]); if (blockToNewVars != null && blockToNewVars.TryGetValue(block, out var newVars) && newVars != null && newVars.Any()) { IList <Identifier> boundVars = newVars .Select(v => (Identifier) new SimpleIdentifier(uniqueNamer.GetName(v, v.Name))).ToList(); IList <TypeIsa> boundVarsTypes = newVars.Select(v => pureTyIsaTransformer.Translate(v.Type)).ToList(); term = new TermQuantifier(TermQuantifier.QuantifierKind.ALL, boundVars, boundVarsTypes, term); } IList <Term> args = blockToActiveVars[block].Select(v => vcExprIsaVisitor.Translate(v)).ToList(); var def = new DefDecl(GetVCDefName(block), new Tuple <IList <Term>, Term>(args, term)); Contract.Assert(!blockToDefVC.ContainsKey(block)); blockToDefVC.Add(block, def); } return(blockToDefVC); }
/// <summary> /// return declarations to rewrite vc expression /// </summary> private List <LemmaDecl> RewriteVcLemmas(Expr expr, bool proveVc, bool hasTypeQuantification) { // To be safe create new erasers (erasers have state that change when certain methods are applied) /* Note that vcExtracted is supposed to be the same as directly erasing translatedVcExpr. The reason we * translate the Boogie expression again to a VC expression before erasing it, is that erasure of a VCExpr * has side effects on that VCExpr. */ Func <bool, int, VCExpr> eraseToVc = (b, i) => _typeEraserFactory.NewEraser(b).TranslateAndErase(expr, i); bool lhsExtractArgs; string proofMethod; if (proveVc) { /* Prove vcNotOptimized ==> vcOptimized. * This is the easier direction, because the type quantifiers in the premise can be directly instantiated * with the extracted versions. */ lhsExtractArgs = false; if (hasTypeQuantification) { proofMethod = "unfolding Let_def using prim_type_vc_lemmas by blast"; } else { proofMethod = "by blast"; } } else { /* Prove vcOptimized ==> vcNotOptimized. * This is the harder direction. */ lhsExtractArgs = true; if (hasTypeQuantification) { proofMethod = "using vc_extractor_lemmas by smt"; } else { proofMethod = "by blast"; } } var lemmaNameNeg = "expr_equiv_" + _lemmaId + "_neg"; var lemmaNamePos = "expr_equiv_" + _lemmaId + "_pos"; _lemmaId++; var lhsNeg = _vcToIsaTranslator.Translate(eraseToVc(lhsExtractArgs, -1)); var lhsPos = _vcToIsaTranslator.Translate(eraseToVc(lhsExtractArgs, 1)); var rhsNeg = _vcToIsaTranslator.Translate(eraseToVc(!lhsExtractArgs, -1)); var rhsPos = _vcToIsaTranslator.Translate(eraseToVc(!lhsExtractArgs, 1)); var result = new List <LemmaDecl> { new LemmaDecl(lemmaNameNeg, TermBinary.MetaImplies(lhsNeg, rhsNeg), new Proof(new List <string> { proofMethod })), new LemmaDecl(lemmaNamePos, TermBinary.MetaImplies(lhsPos, rhsPos), new Proof(new List <string> { proofMethod })) }; return(result); }
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)); }