コード例 #1
0
        public static void AddCheckers(CivlTypeChecker ctc)
        {
            foreach (var action in ctc.AllAtomicActions.Where(a => a.HasPendingAsyncs))
            {
                var requires = action.gate.Select(g => new Requires(false, g.Expr)).ToList();
                var cmds     = new List <Cmd>
                {
                    CmdHelper.CallCmd(
                        action.proc,
                        action.impl.InParams.Select(Expr.Ident).ToList <Expr>(),
                        action.impl.OutParams.Select(Expr.Ident).ToList())
                };
                var blocks = new List <Block>()
                {
                    new Block(Token.NoToken, "init", cmds, CmdHelper.ReturnCmd)
                };

                var PAs     = Expr.Ident(action.impl.OutParams.Last(p => p.TypedIdent.Type.Equals(ctc.pendingAsyncMultisetType)));
                var paBound = VarHelper.BoundVariable("pa", ctc.pendingAsyncType);
                var pa      = Expr.Ident(paBound);

                var nonnegativeExpr =
                    new ForallExpr(Token.NoToken, new List <Variable> {
                    paBound
                },
                                   Expr.Ge(Expr.Select(PAs, pa), Expr.Literal(0)));
                var correctTypeExpr = new ForallExpr(Token.NoToken, new List <Variable> {
                    paBound
                },
                                                     Expr.Imp(
                                                         Expr.Gt(Expr.Select(PAs, pa), Expr.Literal(0)),
                                                         Expr.Or(action.pendingAsyncs.Select(a => ExprHelper.FunctionCall(a.pendingAsyncCtor.membership, pa)))));
                var ensures = new List <Ensures>
                {
                    new Ensures(false, nonnegativeExpr)
                    {
                        ErrorData = $"Action {action.proc.Name} might create negative pending asyncs"
                    },
                    new Ensures(false, correctTypeExpr)
                    {
                        ErrorData = $"Action {action.proc.Name} might create undeclared pending asyncs"
                    },
                };

                CivlUtil.ResolveAndTypecheck(ensures);

                var proc = new Procedure(Token.NoToken, $"PendingAsyncChecker_{action.proc.Name}", new List <TypeVariable>(),
                                         action.impl.InParams, action.impl.OutParams,
                                         requires, action.proc.Modifies, ensures);
                var impl = new Implementation(Token.NoToken, proc.Name, proc.TypeParameters,
                                              proc.InParams, proc.OutParams, new List <Variable>(), blocks)
                {
                    Proc = proc
                };

                ctc.program.AddTopLevelDeclaration(proc);
                ctc.program.AddTopLevelDeclaration(impl);
            }
        }
コード例 #2
0
 private CallCmd GetCallCmd(AtomicAction callee)
 {
     return(CmdHelper.CallCmd(
                callee.proc,
                invariantAction.impl.InParams,
                invariantAction.impl.OutParams.GetRange(0, callee.impl.OutParams.Count)
                ));
 }
コード例 #3
0
 private CallCmd GetCallCmd(AtomicAction callee)
 {
     return(CmdHelper.CallCmd(
                callee.proc,
                invariantAction.impl.InParams.Select(Expr.Ident).ToList <Expr>(),
                invariantAction.impl.OutParams.GetRange(0, callee.impl.OutParams.Count).Select(Expr.Ident).ToList()
                ));
 }
コード例 #4
0
        public static void AddChecks(CivlTypeChecker ctc)
        {
            foreach (var x in ctc.inductiveSequentializations)
            {
                var t = x.GenerateBaseCaseChecker();
                ctc.program.AddTopLevelDeclaration(t.Item1);
                ctc.program.AddTopLevelDeclaration(t.Item2);
                t = x.GenerateConclusionChecker();
                ctc.program.AddTopLevelDeclaration(t.Item1);
                ctc.program.AddTopLevelDeclaration(t.Item2);
                t = x.GenerateStepChecker(ctc.pendingAsyncAdd);
                ctc.program.AddTopLevelDeclaration(t.Item1);
                ctc.program.AddTopLevelDeclaration(t.Item2);
            }

            var absChecks = ctc.inductiveSequentializations.SelectMany(x => x.elim).Where(kv => kv.Key != kv.Value).Distinct();

            foreach (var absCheck in absChecks)
            {
                var action = absCheck.Key;
                var abs    = absCheck.Value;

                var requires = abs.gate.Select(g => new Requires(false, g.Expr)).ToList();
                // TODO: check frame computation
                var frame   = new HashSet <Variable>(action.modifiedGlobalVars.Union(action.gateUsedGlobalVars).Union(abs.modifiedGlobalVars).Union(abs.gateUsedGlobalVars));
                var tr      = TransitionRelationComputation.Refinement(abs, frame);
                var ensures = new List <Ensures> {
                    new Ensures(false, tr)
                    {
                        ErrorData = $"Abstraction {abs.proc.Name} does not summarize {action.proc.Name}"
                    }
                };

                var        subst = InductiveSequentialization.GetSubstitution(action, abs);
                List <Cmd> cmds  = InductiveSequentialization.GetGateAsserts(action, subst,
                                                                             $"Abstraction {abs.proc.Name} fails gate of {action.proc.Name}").ToList <Cmd>();
                cmds.Add(
                    CmdHelper.CallCmd(
                        action.proc,
                        abs.impl.InParams.Select(Expr.Ident).ToList <Expr>(),
                        abs.impl.OutParams.Select(Expr.Ident).ToList()
                        ));
                var blocks = new List <Block> {
                    new Block(Token.NoToken, "init", cmds, CmdHelper.ReturnCmd)
                };

                var proc = new Procedure(Token.NoToken, $"AbstractionCheck_{action.proc.Name}_{abs.proc.Name}", new List <TypeVariable>(),
                                         abs.impl.InParams, abs.impl.OutParams, requires, abs.modifiedGlobalVars.Select(Expr.Ident).ToList(), ensures);
                var impl = new Implementation(Token.NoToken, proc.Name, new List <TypeVariable>(),
                                              proc.InParams, proc.OutParams, new List <Variable>(), blocks)
                {
                    Proc = proc
                };
                ctc.program.AddTopLevelDeclaration(proc);
                ctc.program.AddTopLevelDeclaration(impl);
            }
        }
コード例 #5
0
        public static void AddCheckers(CivlTypeChecker civlTypeChecker)
        {
            foreach (var action in civlTypeChecker.AllAtomicActions.Where(a => a.HasPendingAsyncs))
            {
                var requires = action.gate.Select(g => new Requires(false, g.Expr)).ToList();

                var PAs     = Expr.Ident(action.impl.OutParams.Last(p => p.TypedIdent.Type.Equals(civlTypeChecker.pendingAsyncMultisetType)));
                var paBound = civlTypeChecker.BoundVariable("pa", civlTypeChecker.pendingAsyncType);
                var pa      = Expr.Ident(paBound);

                var nonnegativeExpr =
                    ExprHelper.ForallExpr(new List <Variable> {
                    paBound
                },
                                          Expr.Ge(Expr.Select(PAs, pa), Expr.Literal(0)));
                var correctTypeExpr = ExprHelper.ForallExpr(new List <Variable> {
                    paBound
                },
                                                            Expr.Imp(
                                                                Expr.Gt(Expr.Select(PAs, pa), Expr.Literal(0)),
                                                                Expr.Or(action.pendingAsyncs.Select(a => ExprHelper.FunctionCall(a.pendingAsyncCtor.membership, pa)))));

                CivlUtil.ResolveAndTypecheck(nonnegativeExpr);
                CivlUtil.ResolveAndTypecheck(correctTypeExpr);

                var cmds = new List <Cmd>
                {
                    CmdHelper.CallCmd(
                        action.proc,
                        action.impl.InParams.Select(Expr.Ident).ToList <Expr>(),
                        action.impl.OutParams.Select(Expr.Ident).ToList()),
                    CmdHelper.AssertCmd(
                        action.proc.tok,
                        nonnegativeExpr,
                        $"Action {action.proc.Name} might create negative pending asyncs"),
                    CmdHelper.AssertCmd(
                        action.proc.tok,
                        correctTypeExpr,
                        $"Action {action.proc.Name} might create undeclared pending asyncs")
                };
                var blocks = new List <Block>()
                {
                    BlockHelper.Block("init", cmds)
                };

                var proc = DeclHelper.Procedure(civlTypeChecker.AddNamePrefix($"PendingAsyncChecker_{action.proc.Name}"),
                                                action.impl.InParams, action.impl.OutParams,
                                                requires, action.proc.Modifies, new List <Ensures>());
                var impl = DeclHelper.Implementation(proc, proc.InParams, proc.OutParams, new List <Variable>(), blocks);

                civlTypeChecker.program.AddTopLevelDeclaration(proc);
                civlTypeChecker.program.AddTopLevelDeclaration(impl);
            }
        }
コード例 #6
0
        private static Tuple <Procedure, Implementation> GenerateAbstractionChecker(CivlTypeChecker civlTypeChecker, AtomicAction action, AtomicAction abs)
        {
            var requires = abs.gate.Select(g => new Requires(false, g.Expr)).ToList();
            // TODO: check frame computation
            var frame = new HashSet <Variable>(
                action.modifiedGlobalVars
                .Union(action.gateUsedGlobalVars)
                .Union(abs.modifiedGlobalVars)
                .Union(abs.gateUsedGlobalVars));
            var tr      = TransitionRelationComputation.Refinement(civlTypeChecker, abs, frame);
            var ensures = new List <Ensures> {
                new Ensures(false, tr)
                {
                    ErrorData = $"Abstraction {abs.proc.Name} does not summarize {action.proc.Name}"
                }
            };

            var        subst = InductiveSequentialization.GetSubstitution(action, abs);
            List <Cmd> cmds  = InductiveSequentialization.GetGateAsserts(action, subst,
                                                                         $"Abstraction {abs.proc.Name} fails gate of {action.proc.Name}").ToList <Cmd>();

            cmds.Add(
                CmdHelper.CallCmd(
                    action.proc,
                    abs.impl.InParams.Select(Expr.Ident).ToList <Expr>(),
                    abs.impl.OutParams.Select(Expr.Ident).ToList()
                    ));
            var blocks = new List <Block> {
                new Block(Token.NoToken, "init", cmds, CmdHelper.ReturnCmd)
            };

            var proc = new Procedure(
                Token.NoToken,
                civlTypeChecker.AddNamePrefix($"AbstractionCheck_{action.proc.Name}_{abs.proc.Name}"),
                new List <TypeVariable>(),
                abs.impl.InParams,
                abs.impl.OutParams,
                requires,
                action.proc.Modifies,
                ensures);
            var impl = new Implementation(
                Token.NoToken,
                proc.Name,
                new List <TypeVariable>(),
                proc.InParams,
                proc.OutParams,
                new List <Variable>(),
                blocks)
            {
                Proc = proc
            };

            return(Tuple.Create(proc, impl));
        }
コード例 #7
0
        public Tuple <Procedure, Implementation> GenerateStepChecker(AtomicAction pendingAsync, Function pendingAsyncAdd)
        {
            this.checkName = "step";
            var requires = invariantAction.gate.Select(g => new Requires(false, g.Expr)).ToList();
            var ensures  = new List <Ensures> {
                GetEnsures(GetTransitionRelation(invariantAction))
            };
            var locals = new List <Variable>();

            if (!HasChoice)
            {
                locals.Add(choice.Decl);
            }

            List <Cmd> cmds = new List <Cmd>();

            cmds.Add(GetCallCmd(invariantAction));
            cmds.Add(CmdHelper.AssumeCmd(ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.membership, choice)));
            cmds.Add(CmdHelper.AssumeCmd(Expr.Gt(Expr.Select(PAs, choice), Expr.Literal(0))));
            cmds.Add(RemoveChoice);

            AtomicAction abs = elim[pendingAsync];
            Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>();
            List <Expr> inputExprs          = new List <Expr>();

            for (int i = 0; i < abs.impl.InParams.Count; i++)
            {
                var pendingAsyncParam = ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.selectors[i], choice);
                map[abs.impl.InParams[i]] = pendingAsyncParam;
                inputExprs.Add(pendingAsyncParam);
            }
            var subst = Substituter.SubstitutionFromHashtable(map);

            cmds.AddRange(GetGateAsserts(abs, subst));

            List <IdentifierExpr> outputVars = new List <IdentifierExpr>();

            if (abs.HasPendingAsyncs)
            {
                locals.Add(newPAs.Decl);
                outputVars.Add(newPAs);
            }
            cmds.Add(CmdHelper.CallCmd(abs.proc, inputExprs, outputVars));
            if (abs.HasPendingAsyncs)
            {
                cmds.Add(AddNewPAs(pendingAsyncAdd));
            }
            var blocks = new List <Block> {
                new Block(Token.NoToken, pendingAsync.proc.Name, cmds, CmdHelper.ReturnCmd)
            };

            return(GetCheckerTuple(requires, ensures, locals, blocks, "_" + abs.proc.Name));
        }
コード例 #8
0
        private Implementation WrapperNoninterferenceCheckerImpl()
        {
            var             linearTypeChecker = civlTypeChecker.linearTypeChecker;
            List <Variable> inputs            = new List <Variable>();

            foreach (string domainName in linearTypeChecker.linearDomains.Keys)
            {
                inputs.Add(linearTypeChecker.LinearDomainInFormal(domainName));
            }

            foreach (Variable g in civlTypeChecker.GlobalVariables)
            {
                inputs.Add(OldGlobalFormal(g));
            }

            List <Block> blocks      = new List <Block>();
            TransferCmd  transferCmd = CmdHelper.ReturnCmd;

            if (noninterferenceCheckerDecls.Count > 0)
            {
                List <Block> blockTargets = new List <Block>();
                int          labelCount   = 0;
                foreach (Procedure proc in noninterferenceCheckerDecls.OfType <Procedure>())
                {
                    List <Expr> exprSeq = new List <Expr>();
                    foreach (Variable v in inputs)
                    {
                        exprSeq.Add(Expr.Ident(v));
                    }

                    CallCmd callCmd = CmdHelper.CallCmd(proc, exprSeq, new List <IdentifierExpr>());
                    string  label   = $"L_{labelCount++}";
                    Block   block   = BlockHelper.Block(label, new List <Cmd> {
                        callCmd
                    });
                    blockTargets.Add(block);
                    blocks.Add(block);
                }

                transferCmd = new GotoCmd(Token.NoToken, blockTargets);
            }

            blocks.Insert(0, new Block(Token.NoToken, "enter", new List <Cmd>(), transferCmd));

            var yieldImpl = DeclHelper.Implementation(wrapperNoninterferenceCheckerProc,
                                                      inputs, new List <Variable>(), new List <Variable>(), blocks);

            CivlUtil.AddInlineAttribute(yieldImpl);
            return(yieldImpl);
        }
コード例 #9
0
        private static Tuple <Procedure, Implementation> GenerateAbstractionChecker(CivlTypeChecker civlTypeChecker, AtomicAction action, AtomicAction abs)
        {
            var requires = abs.gate.Select(g => new Requires(false, g.Expr)).ToList();
            // TODO: check frame computation
            var frame = new HashSet <Variable>(
                action.modifiedGlobalVars
                .Union(action.gateUsedGlobalVars)
                .Union(abs.modifiedGlobalVars)
                .Union(abs.gateUsedGlobalVars));

            var        subst = InductiveSequentialization.GetSubstitution(action, abs);
            List <Cmd> cmds  = InductiveSequentialization.GetGateAsserts(action, subst,
                                                                         $"Abstraction {abs.proc.Name} fails gate of {action.proc.Name}").ToList <Cmd>();

            cmds.Add(
                CmdHelper.CallCmd(
                    action.proc,
                    abs.impl.InParams,
                    abs.impl.OutParams
                    ));
            cmds.Add(
                CmdHelper.AssertCmd(
                    abs.proc.tok,
                    TransitionRelationComputation.Refinement(civlTypeChecker, abs, frame),
                    $"Abstraction {abs.proc.Name} does not summarize {action.proc.Name}"
                    ));

            var blocks = new List <Block> {
                BlockHelper.Block("init", cmds)
            };

            var proc = DeclHelper.Procedure(
                civlTypeChecker.AddNamePrefix($"AbstractionCheck_{action.proc.Name}_{abs.proc.Name}"),
                abs.impl.InParams,
                abs.impl.OutParams,
                requires,
                action.proc.Modifies,
                new List <Ensures>());
            var impl = DeclHelper.Implementation(
                proc,
                proc.InParams,
                proc.OutParams,
                new List <Variable>(),
                blocks);

            return(Tuple.Create(proc, impl));
        }
コード例 #10
0
        private IEnumerable <Declaration> PendingAsyncNoninterferenceCheckers()
        {
            if (CommandLineOptions.Clo.TrustNoninterference)
            {
                yield break;
            }

            HashSet <AtomicAction> pendingAsyncsToCheck = new HashSet <AtomicAction>(
                civlTypeChecker.procToAtomicAction.Values
                .Where(a => a.layerRange.Contains(layerNum) && a.HasPendingAsyncs)
                .SelectMany(a => a.pendingAsyncs));

            foreach (var action in pendingAsyncsToCheck)
            {
                var inputs   = action.impl.InParams;
                var outputs  = action.impl.OutParams;
                var requires = action.gate.Select(a => new Requires(false, a.Expr)).ToList();
                var ensures  = new List <Ensures>();
                var modifies = civlTypeChecker.GlobalVariables.Select(Expr.Ident).ToList();
                var locals   = globalSnapshotInstrumentation.NewLocalVars.Union(noninterferenceInstrumentation.NewLocalVars).ToList();
                var cmds     = new List <Cmd>();
                var typeVars = new List <TypeVariable>();

                cmds.AddRange(globalSnapshotInstrumentation.CreateInitCmds());
                cmds.AddRange(noninterferenceInstrumentation.CreateInitCmds(action.impl));
                cmds.Add(CmdHelper.CallCmd(action.proc, inputs, outputs));
                cmds.AddRange(noninterferenceInstrumentation.CreateCallToYieldProc());
                var blocks = new List <Block> {
                    new Block(Token.NoToken, "init", cmds, new ReturnCmd(Token.NoToken))
                };

                var name = civlTypeChecker.AddNamePrefix($"PendingAsyncNoninterferenceChecker_{action.proc.Name}_{layerNum}");
                var proc = new Procedure(Token.NoToken, name, typeVars, inputs, outputs, requires, modifies, ensures);
                var impl = new Implementation(Token.NoToken, name, typeVars, inputs, outputs, locals, blocks)
                {
                    Proc = proc
                };
                yield return(proc);

                yield return(impl);
            }
        }
コード例 #11
0
        public List <Cmd> CreateCallToYieldProc()
        {
            List <Variable> inputs = new List <Variable>();

            foreach (string domainName in linearTypeChecker.linearDomains.Keys)
            {
                inputs.Add(domainNameToHoleVar[domainName]);
            }

            foreach (Variable g in civlTypeChecker.GlobalVariables)
            {
                inputs.Add(oldGlobalMap[g]);
            }

            CallCmd yieldCallCmd = CmdHelper.CallCmd(yieldProc, inputs, new List <Variable>());

            return(new List <Cmd> {
                yieldCallCmd
            });
        }
コード例 #12
0
 private CallCmd ActionCallCmd(AtomicAction action, DeclWithFormals paramProvider)
 {
     return(CmdHelper.CallCmd(action.proc, paramProvider.InParams, paramProvider.OutParams));
 }
コード例 #13
0
ファイル: LinearTypeChecker.cs プロジェクト: smh0960/boogie
    private static void AddChecker(CivlTypeChecker civlTypeChecker, Action action, List<Declaration> decls)
    {
      var linearTypeChecker = civlTypeChecker.linearTypeChecker;
      // Note: The implementation should be used as the variables in the
      //       gate are bound to implementation and not to the procedure.
      Implementation impl = action.impl;
      List<Variable> inputs = impl.InParams;
      List<Variable> outputs = impl.OutParams;

      List<Variable> locals = new List<Variable>(2);
      var paLocal1 = civlTypeChecker.LocalVariable("pa1", civlTypeChecker.pendingAsyncType);
      var paLocal2 = civlTypeChecker.LocalVariable("pa2", civlTypeChecker.pendingAsyncType);
      var pa1 = Expr.Ident(paLocal1);
      var pa2 = Expr.Ident(paLocal2);
      
      if (civlTypeChecker.pendingAsyncType != null)
      {
        locals.Add(paLocal1);
        locals.Add(paLocal2);
      }

      List<Requires> requires = action.gate.Select(a => new Requires(false, a.Expr)).ToList();
      List<LinearityCheck> linearityChecks = new List<LinearityCheck>();

      foreach (var domain in linearTypeChecker.linearDomains.Values)
      {
        // Linear in vars
        var inVars = inputs.Union(action.modifiedGlobalVars)
          .Where(x => linearTypeChecker.FindDomainName(x) == domain.domainName)
          .Where(x => InKinds.Contains(linearTypeChecker.FindLinearKind(x)))
          .Select(Expr.Ident)
          .ToList();
        
        // Linear out vars
        var outVars = inputs.Union(outputs).Union(action.modifiedGlobalVars)
          .Where(x => linearTypeChecker.FindDomainName(x) == domain.domainName)
          .Where(x => OutKinds.Contains(linearTypeChecker.FindLinearKind(x)))
          .Select(Expr.Ident)
          .ToList();

        // First kind
        // Permissions in linear output variables are a subset of permissions in linear input variables.
        if (outVars.Count > 0)
        {
          linearityChecks.Add(new LinearityCheck(
            null,
            OutPermsSubsetInPerms(domain, inVars, outVars),
            $"Potential linearity violation in outputs for domain {domain.domainName}.",
            "variables"));
        }

        if (action is AtomicAction atomicAction && atomicAction.HasPendingAsyncs)
        {
          var PAs = Expr.Ident(atomicAction.impl.OutParams.Last());
          
          foreach (var pendingAsync in atomicAction.pendingAsyncs)
          {
            var pendingAsyncLinearParams = PendingAsyncLinearParams(linearTypeChecker, domain, pendingAsync, pa1);

            if (pendingAsyncLinearParams.Count == 0) continue;

            // Second kind
            // Permissions in linear output variables + linear inputs of a single pending async
            // are a subset of permissions in linear input variables.
            var exactlyOnePA = Expr.And(
              ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.membership, pa1),
              Expr.Eq(Expr.Select(PAs, pa1), Expr.Literal(1)));
            var outSubsetInExpr = OutPermsSubsetInPerms(domain, inVars, pendingAsyncLinearParams.Union(outVars));
            linearityChecks.Add(new LinearityCheck(
              exactlyOnePA,
              outSubsetInExpr,
              $"Potential linearity violation in outputs and pending async of {pendingAsync.proc.Name} for domain {domain.domainName}.",
              $"single_{pendingAsync.proc.Name}"));

            // Third kind
            // If there are two identical pending asyncs, then their input permissions mut be empty.
            var twoIdenticalPAs = Expr.And(
              ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.membership, pa1),
              Expr.Ge(Expr.Select(PAs, pa1), Expr.Literal(2)));
            var emptyPerms = OutPermsSubsetInPerms(domain, Enumerable.Empty<Expr>(), pendingAsyncLinearParams);
            linearityChecks.Add(new LinearityCheck(
              twoIdenticalPAs,
              emptyPerms,
              $"Potential linearity violation in identical pending asyncs of {pendingAsync.proc.Name} for domain {domain.domainName}.",
              $"identical_{pendingAsync.proc.Name}"));
          }

          var pendingAsyncs = atomicAction.pendingAsyncs.ToList();
          for (int i = 0; i < pendingAsyncs.Count; i++)
          {
            var pendingAsync1 = pendingAsyncs[i];
            for (int j = i; j < pendingAsyncs.Count; j++)
            {
              var pendingAsync2 = pendingAsyncs[j];

              var pendingAsyncLinearParams1 = PendingAsyncLinearParams(linearTypeChecker, domain, pendingAsync1, pa1);
              var pendingAsyncLinearParams2 = PendingAsyncLinearParams(linearTypeChecker, domain, pendingAsync2, pa2);
              
              if (pendingAsyncLinearParams1.Count == 0 || pendingAsyncLinearParams2.Count == 0) continue;

              // Fourth kind
              // Input permissions of two non-identical pending asyncs (possibly of the same action)
              // are a subset of permissions in linear input variables.
              var membership = Expr.And(
                Expr.Neq(pa1, pa2),
                Expr.And(
                  ExprHelper.FunctionCall(pendingAsync1.pendingAsyncCtor.membership, pa1),
                  ExprHelper.FunctionCall(pendingAsync2.pendingAsyncCtor.membership, pa2)));

              var existing = Expr.And(
                Expr.Ge(Expr.Select(PAs, pa1), Expr.Literal(1)),
                Expr.Ge(Expr.Select(PAs, pa2), Expr.Literal(1)));

              var noDuplication = OutPermsSubsetInPerms(domain, inVars, pendingAsyncLinearParams1.Union(pendingAsyncLinearParams2));

              linearityChecks.Add(new LinearityCheck(
                Expr.And(membership, existing),
                noDuplication,
                $"Potential lnearity violation in pending asyncs of {pendingAsync1.proc.Name} and {pendingAsync2.proc.Name} for domain {domain.domainName}.",
                $"distinct_{pendingAsync1.proc.Name}_{pendingAsync2.proc.Name}"));
            }
          }
        }
      }

      if (linearityChecks.Count == 0) return;

      // Create checker blocks
      List<Block> checkerBlocks = new List<Block>(linearityChecks.Count);
      foreach (var lc in linearityChecks)
      {
        List<Cmd> cmds = new List<Cmd>(2);
        if (lc.assume != null)
        {
          cmds.Add(CmdHelper.AssumeCmd(lc.assume));
        }
        cmds.Add(new AssertCmd(action.proc.tok, lc.assert) { ErrorData = lc.message });
        var block = new Block(Token.NoToken, lc.name, cmds, CmdHelper.ReturnCmd);
        CivlUtil.ResolveAndTypecheck(block, ResolutionContext.State.Two);
        checkerBlocks.Add(block);
      }
      
      // Create init blocks
      List<Block> blocks = new List<Block>(linearityChecks.Count + 1);
      blocks.Add(
        new Block(
          Token.NoToken,
          "init",
          new List<Cmd> { CmdHelper.CallCmd(action.proc, inputs, outputs) },
          new GotoCmd(Token.NoToken, checkerBlocks)));
      blocks.AddRange(checkerBlocks);

      // Create the whole check procedure
      string checkerName = civlTypeChecker.AddNamePrefix($"LinearityChecker_{action.proc.Name}");
      Procedure linCheckerProc = new Procedure(Token.NoToken, checkerName, new List<TypeVariable>(),
        inputs, outputs, requires, action.proc.Modifies, new List<Ensures>());
      Implementation linCheckImpl = new Implementation(Token.NoToken, checkerName,
        new List<TypeVariable>(), inputs, outputs, locals, blocks);
      linCheckImpl.Proc = linCheckerProc;
      decls.Add(linCheckImpl);
      decls.Add(linCheckerProc);
    }
コード例 #14
0
        public Tuple <Procedure, Implementation> GenerateStepChecker(Function pendingAsyncAdd)
        {
            this.checkName = "step";
            var requires = invariantAction.gate.Select(g => new Requires(false, g.Expr)).ToList();
            var ensures  = new List <Ensures> {
                GetEnsures(GetTransitionRelation(invariantAction))
            };
            var locals = new List <Variable>();

            if (elim.Values.Any(a => a.HasPendingAsyncs))
            {
                locals.Add(newPAs.Decl);
            }

            List <Block> blocks = new List <Block>();

            foreach (var pendingAsync in elim.Keys)
            {
                AtomicAction abs = elim[pendingAsync];

                Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>();
                List <Expr> inputExprs          = new List <Expr>();
                for (int i = 0; i < abs.impl.InParams.Count; i++)
                {
                    var pendingAsyncParam = ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.selectors[i], choice);
                    map[abs.impl.InParams[i]] = pendingAsyncParam;
                    inputExprs.Add(pendingAsyncParam);
                }
                var subst = Substituter.SubstitutionFromHashtable(map);
                List <IdentifierExpr> outputVars = new List <IdentifierExpr>();
                if (abs.HasPendingAsyncs)
                {
                    outputVars.Add(newPAs);
                }

                List <Cmd> cmds = new List <Cmd>();
                cmds.Add(CmdHelper.AssumeCmd(ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.membership, choice)));
                cmds.AddRange(GetGateAsserts(abs, subst));
                cmds.Add(CmdHelper.CallCmd(abs.proc, inputExprs, outputVars));
                if (abs.HasPendingAsyncs)
                {
                    cmds.Add(AddNewPAs(pendingAsyncAdd));
                }
                var block = new Block(Token.NoToken, pendingAsync.proc.Name, cmds, CmdHelper.ReturnCmd);
                blocks.Add(block);
            }

            {
                List <Cmd> cmds = new List <Cmd>();
                cmds.Add(GetCallCmd(invariantAction));
                if (HasChoice)
                {
                    cmds.Add(new AssumeCmd(Token.NoToken, ValidChoiceExpr));
                    cmds.Add(
                        new AssertCmd(Token.NoToken, ElimPendingAsyncExpr(choice))
                    {
                        ErrorData = $"Failed to validate choice in IS of {inputAction.proc.Name}"
                    }
                        );
                }
                else
                {
                    locals.Add(choice.Decl);
                    cmds.Add(new AssumeCmd(Token.NoToken, ElimPendingAsyncExpr(choice)));
                }
                cmds.Add(RemoveChoice);
                var initBlock = new Block(Token.NoToken, "init", cmds, new GotoCmd(Token.NoToken, blocks.ToList()));
                blocks.Insert(0, initBlock);
            }

            return(GetCheckerTuple(requires, ensures, locals, blocks));
        }