Ejemplo n.º 1
0
        public void Transform()
        {
            foreach (var decl in program.TopLevelDeclarations)
            {
                Implementation impl = decl as Implementation;
                if (impl == null)
                {
                    continue;
                }
                Dictionary <string, Variable> domainNameToInputVar = new Dictionary <string, Variable>();
                foreach (string domainName in linearDomains.Keys)
                {
                    var    domain = linearDomains[domainName];
                    Formal f      = new Formal(
                        Token.NoToken,
                        new TypedIdent(Token.NoToken,
                                       "linear_" + domainName + "_in",
                                       new MapType(Token.NoToken, new List <TypeVariable>(),
                                                   new List <Type> {
                        domain.elementType
                    }, Type.Bool)), true);
                    impl.InParams.Add(f);
                    domainNameToInputVar[domainName] = f;
                }

                foreach (Block b in impl.Blocks)
                {
                    List <Cmd> newCmds = new List <Cmd>();
                    for (int i = 0; i < b.Cmds.Count; i++)
                    {
                        Cmd cmd = b.Cmds[i];
                        newCmds.Add(cmd);
                        if (cmd is CallCmd)
                        {
                            CallCmd callCmd = cmd as CallCmd;
                            if (callCmd.IsAsync)
                            {
                                foreach (var domainName in linearDomains.Keys)
                                {
                                    var domain = linearDomains[domainName];
                                    var expr   = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List <Expr> {
                                        Expr.False
                                    });
                                    expr.Resolve(new ResolutionContext(null));
                                    expr.Typecheck(new TypecheckingContext(null));
                                    callCmd.Ins.Add(expr);
                                }
                            }
                            else
                            {
                                Dictionary <string, Expr> domainNameToExpr = new Dictionary <string, Expr>();
                                foreach (var domainName in linearDomains.Keys)
                                {
                                    domainNameToExpr[domainName] = new IdentifierExpr(Token.NoToken, domainNameToInputVar[domainName]);
                                }
                                foreach (Variable v in availableLinearVars[callCmd])
                                {
                                    var            domainName = FindDomainName(v);
                                    var            domain     = linearDomains[domainName];
                                    IdentifierExpr ie         = new IdentifierExpr(Token.NoToken, v);
                                    var            expr       = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool),
                                                                             new List <Expr> {
                                        v.TypedIdent.Type is MapType ? ie : Singleton(ie, domainName), domainNameToExpr[domainName]
                                    });
                                    expr.Resolve(new ResolutionContext(null));
                                    expr.Typecheck(new TypecheckingContext(null));
                                    domainNameToExpr[domainName] = expr;
                                }
                                foreach (var domainName in linearDomains.Keys)
                                {
                                    callCmd.Ins.Add(domainNameToExpr[domainName]);
                                }
                            }
                        }
                        else if (cmd is ParCallCmd)
                        {
                            ParCallCmd parCallCmd = (ParCallCmd)cmd;
                            foreach (CallCmd callCmd in parCallCmd.CallCmds)
                            {
                                foreach (var domainName in linearDomains.Keys)
                                {
                                    var domain = linearDomains[domainName];
                                    var expr   = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List <Expr> {
                                        Expr.False
                                    });
                                    expr.Resolve(new ResolutionContext(null));
                                    expr.Typecheck(new TypecheckingContext(null));
                                    callCmd.Ins.Add(expr);
                                }
                            }
                        }
                        else if (cmd is YieldCmd)
                        {
                            AddDisjointnessExpr(newCmds, cmd, domainNameToInputVar);
                        }
                    }
                    b.Cmds = newCmds;
                }

                {
                    // Loops
                    impl.PruneUnreachableBlocks();
                    impl.ComputePredecessorsForBlocks();
                    GraphUtil.Graph <Block> g = Program.GraphFromImpl(impl);
                    g.ComputeLoops();
                    if (g.Reducible)
                    {
                        foreach (Block header in g.Headers)
                        {
                            List <Cmd> newCmds = new List <Cmd>();
                            AddDisjointnessExpr(newCmds, header, domainNameToInputVar);
                            newCmds.AddRange(header.Cmds);
                            header.Cmds = newCmds;
                        }
                    }
                }
            }

            foreach (var decl in program.TopLevelDeclarations)
            {
                Procedure proc = decl as Procedure;
                if (proc == null)
                {
                    continue;
                }

                Dictionary <string, HashSet <Variable> > domainNameToInputScope  = new Dictionary <string, HashSet <Variable> >();
                Dictionary <string, HashSet <Variable> > domainNameToOutputScope = new Dictionary <string, HashSet <Variable> >();
                foreach (var domainName in linearDomains.Keys)
                {
                    domainNameToInputScope[domainName]  = new HashSet <Variable>();
                    domainNameToOutputScope[domainName] = new HashSet <Variable>();
                }
                foreach (Variable v in globalVarToDomainName.Keys)
                {
                    var domainName = globalVarToDomainName[v];
                    domainNameToInputScope[domainName].Add(v);
                    domainNameToOutputScope[domainName].Add(v);
                }
                foreach (Variable v in proc.InParams)
                {
                    var domainName = FindDomainName(v);
                    if (domainName == null)
                    {
                        continue;
                    }
                    domainNameToInputScope[domainName].Add(v);
                }
                foreach (Variable v in proc.OutParams)
                {
                    var domainName = FindDomainName(v);
                    if (domainName == null)
                    {
                        continue;
                    }
                    domainNameToOutputScope[domainName].Add(v);
                }
                foreach (var domainName in linearDomains.Keys)
                {
                    proc.Requires.Add(new Requires(true, DisjointnessExpr(domainName, domainNameToInputScope[domainName])));
                    var    domain = linearDomains[domainName];
                    Formal f      = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List <TypeVariable>(), new List <Type> {
                        domain.elementType
                    }, Type.Bool)), true);
                    proc.InParams.Add(f);
                    domainNameToOutputScope[domainName].Add(f);
                    proc.Ensures.Add(new Ensures(true, DisjointnessExpr(domainName, domainNameToOutputScope[domainName])));
                }
            }

            foreach (LinearDomain domain in linearDomains.Values)
            {
                program.TopLevelDeclarations.Add(domain.mapConstBool);
                program.TopLevelDeclarations.Add(domain.mapConstInt);
                program.TopLevelDeclarations.Add(domain.mapEqInt);
                program.TopLevelDeclarations.Add(domain.mapImpBool);
                program.TopLevelDeclarations.Add(domain.mapOrBool);
                foreach (Axiom axiom in domain.axioms)
                {
                    program.TopLevelDeclarations.Add(axiom);
                }
            }

            //int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
            //CommandLineOptions.Clo.PrintUnstructured = 1;
            //PrintBplFile("lsd.bpl", program, false, false);
            //CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
        }
Ejemplo n.º 2
0
    public override Implementation VisitImplementation(Implementation node)
    {
      if (civlTypeChecker.procToAtomicAction.ContainsKey(node.Proc) ||
          civlTypeChecker.procToIntroductionAction.ContainsKey(node.Proc) ||
          civlTypeChecker.procToLemmaProc.ContainsKey(node.Proc))
        return node;

      node.PruneUnreachableBlocks();
      node.ComputePredecessorsForBlocks();
      GraphUtil.Graph<Block> graph = Program.GraphFromImpl(node);
      graph.ComputeLoops();

      HashSet<Variable> start = new HashSet<Variable>(globalVarToDomainName.Keys);
      for (int i = 0; i < node.InParams.Count; i++)
      {
        Variable v = node.Proc.InParams[i];
        string domainName = FindDomainName(v);
        if (domainName != null)
        {
          var kind = FindLinearKind(v);
          inParamToLinearQualifier[node.InParams[i]] = new LinearQualifier(domainName, kind);
          if (kind == LinearKind.LINEAR || kind == LinearKind.LINEAR_IN)
          {
            start.Add(node.InParams[i]);
          }
        }
      }

      for (int i = 0; i < node.OutParams.Count; i++)
      {
        string domainName = FindDomainName(node.Proc.OutParams[i]);
        if (domainName != null)
        {
          outParamToDomainName[node.OutParams[i]] = domainName;
        }
      }

      var oldErrorCount = checkingContext.ErrorCount;
      var impl = base.VisitImplementation(node);
      if (oldErrorCount < checkingContext.ErrorCount)
        return impl;

      Stack<Block> dfsStack = new Stack<Block>();
      HashSet<Block> dfsStackAsSet = new HashSet<Block>();
      availableLinearVars[node.Blocks[0]] = start;
      dfsStack.Push(node.Blocks[0]);
      dfsStackAsSet.Add(node.Blocks[0]);
      while (dfsStack.Count > 0)
      {
        Block b = dfsStack.Pop();
        dfsStackAsSet.Remove(b);
        HashSet<Variable> end = PropagateAvailableLinearVarsAcrossBlock(b);
        if (b.TransferCmd is ReturnCmd)
        {
          foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(end))
          {
            Error(b.TransferCmd, $"Global variable {g.Name} must be available at a return");
          }

          foreach (Variable v in node.InParams)
          {
            if (FindDomainName(v) == null || FindLinearKind(v) == LinearKind.LINEAR_IN || end.Contains(v)) continue;
            Error(b.TransferCmd, $"Input variable {v.Name} must be available at a return");
          }

          foreach (Variable v in node.OutParams)
          {
            if (FindDomainName(v) == null || end.Contains(v)) continue;
            Error(b.TransferCmd, $"Output variable {v.Name} must be available at a return");
          }

          continue;
        }

        GotoCmd gotoCmd = b.TransferCmd as GotoCmd;
        foreach (Block target in gotoCmd.labelTargets)
        {
          if (!availableLinearVars.ContainsKey(target))
          {
            availableLinearVars[target] = new HashSet<Variable>(end);
            dfsStack.Push(target);
            dfsStackAsSet.Add(target);
          }
          else
          {
            var savedAvailableVars = new HashSet<Variable>(availableLinearVars[target]);
            availableLinearVars[target].IntersectWith(end);
            if (savedAvailableVars.IsProperSupersetOf(availableLinearVars[target]) && !dfsStackAsSet.Contains(target))
            {
              dfsStack.Push(target);
              dfsStackAsSet.Add(target);
            }
          }
        }
      }

      if (graph.Reducible)
      {
        foreach (Block header in graph.Headers)
        {
          foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(availableLinearVars[header]))
          {
            Error(header, $"Global variable {g.Name} must be available at a loop head");
          }
        }
      }

      return impl;
    }