コード例 #1
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 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(civlTypeChecker.pendingAsyncMultisetType)));
                var paBound = civlTypeChecker.BoundVariable("pa", civlTypeChecker.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, civlTypeChecker.AddNamePrefix($"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
                };

                civlTypeChecker.program.AddTopLevelDeclaration(proc);
                civlTypeChecker.program.AddTopLevelDeclaration(impl);
            }
        }