public PassificationLemmaManager(
            CFGRepr cfg,
            IDictionary <Block, Block> origToPassiveBlock,
            IProgramAccessor programAccessor,
            IProgramAccessor passiveProgramAccessor,
            Tuple <string, string> varContextNonPassivePassive,
            StateRelationData oldStateRelationData,
            PassiveRelationGen relationGen,
            IVariableTranslationFactory varTranslationFactory,
            IVariableTranslationFactory passiveTranslationFactory)
        {
            this.cfg = cfg;
            this.origToPassiveBlock     = origToPassiveBlock;
            this.programAccessor        = programAccessor;
            this.passiveProgramAccessor = passiveProgramAccessor;
            _oldStateRelationData       = oldStateRelationData;
            _relationGen          = relationGen;
            initState             = IsaBoogieTerm.Normal(normalInitState);
            varTranslation        = varTranslationFactory.CreateTranslation().VarTranslation;
            passiveVarTranslation = passiveTranslationFactory.CreateTranslation().VarTranslation;
            //separate unique namer for function interpretations (since they already have a name in uniqueNamer): possible clashes

            boogieContext = new BoogieContextIsa(
                IsaCommonTerms.TermIdentFromName("A"),
                IsaCommonTerms.TermIdentFromName("M"),
                IsaCommonTerms.TermIdentFromName(varContextNonPassivePassive.Item1),
                IsaCommonTerms.TermIdentFromName("\\<Gamma>"),
                IsaCommonTerms.TermIdentFromName("\\<Omega>")
                );
            passiveVarContext = IsaCommonTerms.TermIdentFromName(varContextNonPassivePassive.Item2);
        }
예제 #2
0
        /// <summary>
        /// Provide program for the next procedure (for the global declarations).
        /// </summary>
        public static void Program(Program p)
        {
            if (boogieGlobalData == null)
            {
                boogieGlobalData = new BoogieGlobalData(p.Functions, p.Axioms, p.GlobalVariables, p.Constants);

                var methodData            = BoogieMethodData.CreateOnlyGlobal(boogieGlobalData);
                var fixedVarTranslation   = new DeBruijnFixedVarTranslation(methodData);
                var fixedTyVarTranslation = new DeBruijnFixedTVarTranslation(methodData);
                var factory =
                    new DeBruijnVarFactory(fixedVarTranslation, fixedTyVarTranslation, boogieGlobalData);
                var globalDataTheoryName = "global_data";
                var globalDataConfig     = new IsaProgramGeneratorConfig(null, true, true, true, false, SpecsConfig.None, false);
                globalDataProgAccess = new IsaProgramGenerator().GetIsaProgram(
                    globalDataTheoryName,
                    "proc",
                    methodData, globalDataConfig, factory,
                    null,
                    out var declsGlobalData,
                    !CommandLineOptions.Clo.GenerateIsaProgNoProofs,
                    true
                    );

                var globalDataTheory = new Theory(globalDataTheoryName,
                                                  new List <string> {
                    "Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util"
                },
                                                  declsGlobalData);
                ProofGenerationOutput.StoreTheoriesTopLevel(new List <Theory> {
                    globalDataTheory
                });
            }
        }
 private DefDecl MethodDefinition(IProgramAccessor programAccessor, BoogieMethodData methodData, SpecsConfig specConfig)
 {
     var modifiedVarsTerm = new TermList(
         methodData.ModifiedVars.Select(id =>
     {
         if (varTranslation.VarTranslation.TryTranslateVariableId(id.Decl, out Term idTerm, out _))
         {
             return(idTerm);
         }
예제 #4
0
 public static Term AxiomAssumption(BoogieContextIsa boogieContext, IProgramAccessor programAccessor,
                                    Term normalState)
 {
     return
         (IsaBoogieTerm.AxiomAssm(
              boogieContext.absValTyMap,
              boogieContext.funContext,
              IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()),
              normalState,
              programAccessor.AxiomsDecl()
              ));
 }
        public MembershipLemmaManager(
            IsaProgramGeneratorConfig config,
            IsaProgramRepr isaProgramRepr,
            IsaBlockInfo isaBlockInfo,
            Tuple <int, int> GlobalsMaxLocalsMin,
            IVariableTranslationFactory factory,
            string theoryName
            )
        {
            parent = config.parentAccessor;
            this.isaProgramRepr = isaProgramRepr;
            this.factory        = factory;
            this.theoryName     = theoryName;
            this.config         = config;
            this.isaBlockInfo   = isaBlockInfo;
            typeIsaVisitor      = new TypeIsaVisitor(factory.CreateTranslation().TypeVarTranslation);
            basicCmdIsaVisitor  = new BasicCmdIsaVisitor(factory);
            paramsAndLocalsDefs =
                new[] { isaProgramRepr.paramsDeclDef + "_def", isaProgramRepr.localVarsDeclDef + "_def" };

            parameters = config.generateParamsAndLocals
                ? QualifyAccessName(isaProgramRepr.paramsDeclDef)
                : parent.ParamsDecl();
            locals = config.generateParamsAndLocals
                ? QualifyAccessName(isaProgramRepr.localVarsDeclDef)
                : parent.LocalsDecl();
            paramsAndLocalsList =
                IsaCommonTerms.AppendList(IsaCommonTerms.TermIdentFromName(parameters),
                                          IsaCommonTerms.TermIdentFromName(locals));

            consts = config.generateGlobalsAndConstants
                ? QualifyAccessName(isaProgramRepr.GlobalProgramRepr.constantsDeclDef)
                : parent.ConstsDecl();
            globals = config.generateGlobalsAndConstants
                ? QualifyAccessName(isaProgramRepr.GlobalProgramRepr.globalsDeclDef)
                : parent.GlobalsDecl();

            constsAndGlobalsDefs =
                new[] { consts + "_def", globals + "_def" };
            constsAndGlobalsList =
                IsaCommonTerms.AppendList(IsaCommonTerms.TermIdentFromName(consts),
                                          IsaCommonTerms.TermIdentFromName(globals));
            AddDisjointnessLemmas(GlobalsMaxLocalsMin.Item1, GlobalsMaxLocalsMin.Item2);
            AddWellFormednessLemmas();
        }
 public IsaProgramGeneratorConfig(
     IProgramAccessor parent,
     bool generateFunctions,
     bool generateAxioms,
     bool generateGlobalsAndConstants,
     bool generateParamsAndLocals,
     SpecsConfig specsConfig,
     bool generateVarContextWfLemma
     )
 {
     parentAccessor                   = parent;
     this.generateFunctions           = generateFunctions;
     this.generateAxioms              = generateAxioms;
     this.specsConfig                 = specsConfig;
     this.generateGlobalsAndConstants = generateGlobalsAndConstants;
     this.generateParamsAndLocals     = generateParamsAndLocals;
     this.generateVarContextWfLemma   = generateVarContextWfLemma;
 }
        public IEnumerable <OuterDecl> EndToEndProof(
            string entryCfgLemma,
            string boogieToVcLemma,
            Term vcAssm,
            IProgramAccessor programAccessor,
            IProgramAccessor passiveProgramAccessor,
            Tuple <string, string> varContextNonPassivePassive,
            StateRelationData oldRelationData,
            CFGRepr cfg,
            IEnumerable <Variable> liveEntryVars,
            IVariableTranslation <Variable> varTranslation)
        {
            this.entryCfgLemma          = entryCfgLemma;
            this.boogieToVcLemma        = boogieToVcLemma;
            this.vcAssm                 = vcAssm;
            this.programAccessor        = programAccessor;
            this.passiveProgramAccessor = passiveProgramAccessor;
            boogieContext               = new BoogieContextIsa(
                IsaCommonTerms.TermIdentFromName("A"),
                IsaCommonTerms.TermIdentFromName("M"),
                IsaCommonTerms.TermIdentFromName(varContextNonPassivePassive.Item1),
                IsaCommonTerms.TermIdentFromName("\\<Gamma>"),
                IsaCommonTerms.EmptyList
                );
            passiveVarContext    = IsaCommonTerms.TermIdentFromName(varContextNonPassivePassive.Item2);
            this.oldRelationData = oldRelationData;
            this.cfg             = cfg;
            this.liveEntryVars   = liveEntryVars;
            this.varTranslation  = varTranslation;

            var locale = new LocaleDecl("glue_proof",
                                        Context(),
                                        GenerateLemma()
                                        );

            return(new List <OuterDecl>
            {
                locale
            });
        }
        public IEnumerable <OuterDecl> EndToEndProof(
            string entryCfgLemma,
            string passificationEndToEndLemma,
            Term vcAssm,
            IProgramAccessor programAccessor,
            CFGRepr cfg)
        {
            this.programAccessor = programAccessor;
            boogieContext        = new BoogieContextIsa(
                IsaCommonTerms.TermIdentFromName("A"),
                IsaCommonTerms.TermIdentFromName("M"),
                IsaCommonTerms.TermIdentFromName(varContextName),
                IsaCommonTerms.TermIdentFromName("\\<Gamma>"),
                IsaCommonTerms.EmptyList
                );

            var abbrev = new AbbreviationDecl(
                varContextName,
                new Tuple <IList <Term>, Term>(new List <Term>(),
                                               new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl()))
                );
            var result = new List <OuterDecl> {
                abbrev
            };

            var kStepRed = IsaBoogieTerm.RedCFGKStep(
                BoogieContextIsa.CreateWithNewVarContext(
                    boogieContext,
                    new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl())
                    ),
                programAccessor.CfgDecl(),
                IsaBoogieTerm.CFGConfigNode(new NatConst(cfg.GetUniqueIntLabel(cfg.entry)),
                                            IsaBoogieTerm.Normal(normalInitState)),
                IsaCommonTerms.TermIdentFromName("j"),
                IsaBoogieTerm.CFGConfig(finalNodeOrReturn, finalState)
                );

            var proofSb = new StringBuilder();

            proofSb.AppendLine("proof -");
            proofSb.AppendLine("from " + redAssmName + " obtain j where Aux:" + "\"" + kStepRed + "\"");
            proofSb.AppendLine("by (meson rtranclp_imp_relpowp)");
            proofSb.AppendLine("show ?thesis");
            proofSb.AppendLine(ProofUtil.Apply("rule " + entryCfgLemma));
            //TODO: don't hardcode this
            proofSb.AppendLine("unfolding cfg_to_dag_lemmas_def");
            proofSb.AppendLine(ProofUtil.Apply("rule " + finterpAssmName));
            proofSb.AppendLine("apply (rule Aux)");
            proofSb.AppendLine("apply (rule dag_lemma_assms_same)");
            proofSb.AppendLine("unfolding state_well_typed_def");
            proofSb.AppendLine("apply (intro conjI)");
            proofSb.AppendLine("using " + paramsLocalsAssmName + " apply simp");
            proofSb.AppendLine("using " + constsGlobalsAssmName + " apply simp");
            proofSb.AppendLine("using " + constsGlobalsAssmName + " " + oldGlobalAssmName + " apply simp");
            proofSb.AppendLine("using " + binderEmptyAssmName + " apply simp");
            proofSb.AppendLine(ProofUtil.Apply("rule " + passificationEndToEndLemma));
            //TODO: don't hardcode this
            proofSb.AppendLine("unfolding glue_proof_def");
            proofSb.AppendLine("apply (intro conjI)");
            proofSb.AppendLine("apply assumption");
            proofSb.AppendLine("using " + vcAssmName + " apply simp");
            proofSb.AppendLine("using " + closedAssmName + " apply simp");
            proofSb.AppendLine("using " + nonEmptyTypesAssmName + " apply simp");
            proofSb.AppendLine(ProofUtil.Apply("rule " + finterpAssmName));
            proofSb.AppendLine("using " + axiomAssmName + " apply simp");
            proofSb.AppendLine("using " + paramsLocalsAssmName + " apply simp");
            proofSb.AppendLine("using " + constsGlobalsAssmName + " apply simp");
            proofSb.AppendLine("using " + binderEmptyAssmName + " apply simp");
            proofSb.AppendLine("using " + oldGlobalAssmName + " apply simp");
            proofSb.AppendLine("using " + preconditionsAssmName + " apply simp");
            proofSb.AppendLine("done");
            proofSb.AppendLine("qed");

            var helperLemmaName = "end_to_end_theorem_aux";

            var helperLemma =
                new LemmaDecl(
                    helperLemmaName,
                    LemmaContext(cfg, vcAssm),
                    CfgToDagLemmaManager.CfgLemmaConclusion(boogieContext, programAccessor.PostconditionsDecl(),
                                                            finalNodeOrReturn, finalState),
                    new Proof(new List <string> {
                proofSb.ToString()
            })
                    );

            result.Add(helperLemma);
            //transform end to end theorem to a compact representation

            var endToEndLemma =
                new LemmaDecl(
                    "end_to_end_theorem",
                    ContextElem.CreateWithAssumptions(new List <Term> {
                vcAssm
            }, new List <string> {
                "VC"
            }),
                    ProcedureIsCorrect(
                        programAccessor.FunctionsDecl(),
                        IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()),
                        IsaCommonTerms.TermIdentFromName(programAccessor.GlobalsDecl()),
                        programAccessor.AxiomsDecl(),
                        programAccessor.ProcDecl()),
                    new Proof(
                        new List <string>
            {
                ProofUtil.Apply(ProofUtil.Rule(ProofUtil.OF("end_to_end_util", helperLemmaName))),
                "apply assumption " + "using VC apply simp " + " apply assumption+",
                ProofUtil.By("simp_all add: exprs_to_only_checked_spec_1 exprs_to_only_checked_spec_2 " +
                             programAccessor.ProcDeclName() + "_def " + programAccessor.CfgDeclName() + "_def")
            }
                        ));

            result.Add(endToEndLemma);
            return(result);
        }
예제 #9
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));
        }
예제 #10
0
        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));
        }
        /**
         * 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
                       ));
        }
예제 #12
0
 public TypingTacticGenerator(IProgramAccessor programAccessor, IVariableTranslationFactory factory)
 {
     this.programAccessor  = programAccessor;
     equalityHintGenerator = new EqualityHintGenerator(factory);
 }