Esempio n. 1
0
        /// <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);
                }
Esempio n. 2
0
        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));
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 7
0
        /// <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
            };
        }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
 public VCBlockToIsaTranslator(IsaUniqueNamer uniqueNamer)
 {
     this.uniqueNamer = uniqueNamer;
 }
Esempio n. 10
0
 public void setFunctionNamer(IsaUniqueNamer functionNamer)
 {
     _uniqueNamer = functionNamer;
 }
 private static string GetCfgLemmaName(Block b, IsaUniqueNamer namer)
 {
     return("cfg_" + namer.GetName(b, "block_" + b.Label));
 }
Esempio n. 12
0
        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
                       ));
        }
Esempio n. 15
0
        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));
 }
Esempio n. 19
0
        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));
        }
Esempio n. 20
0
 public VCExprToIsaTranslator(IsaUniqueNamer uniqueNamer) :
     this(uniqueNamer, new Dictionary <Block, DefDecl>(), new Dictionary <Block, IList <VCExprVar> >())
 {
 }
Esempio n. 21
0
        /// <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;
 }