public static Expr Extract(Expr expr, Program program, List <Axiom> axioms)
        {
            Contract.Requires(expr != null && program != null && !program.TopLevelDeclarationsAreFrozen && axioms != null);

            if (expr is LiteralExpr)
            {
                return(expr);
            }

            var extractor = new FunctionExtractor();

            var body = extractor.VisitExpr(expr);

            var name         = program.FreshExtractedFunctionName();
            var originalVars = extractor.Substitutions.Keys.ToList();
            var formalInArgs = originalVars.Select(v => new Formal(Token.NoToken, new TypedIdent(Token.NoToken, extractor.Substitutions[v].Name, extractor.Substitutions[v].TypedIdent.Type), true)).ToList <Variable>();
            var formalOutArg = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, name + "$result$", expr.Type), false);
            var func         = new Function(Token.NoToken, name, formalInArgs, formalOutArg);

            func.AddAttribute("never_pattern");

            var boundVars = originalVars.Select(k => extractor.Substitutions[k]);
            var axiomCall = new NAryExpr(Token.NoToken, new FunctionCall(func), boundVars.Select(b => new IdentifierExpr(Token.NoToken, b)).ToList <Expr>());

            axiomCall.Type           = expr.Type;
            axiomCall.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
            var eq = LiteralExpr.Eq(axiomCall, body);

            eq.Type           = body.Type;
            eq.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
            if (0 < formalInArgs.Count)
            {
                var forallExpr = new ForallExpr(Token.NoToken, boundVars.ToList <Variable>(), new Trigger(Token.NoToken, true, new List <Expr> {
                    axiomCall
                }), eq);
                body = forallExpr;
                forallExpr.Attributes = new QKeyValue(Token.NoToken, "weight", new List <object> {
                    new LiteralExpr(Token.NoToken, Basetypes.BigNum.FromInt(30))
                }, null);
                body.Type = Type.Bool;
            }
            else
            {
                body = eq;
            }

            var axiom = new Axiom(Token.NoToken, body);

            func.DefinitionAxiom = axiom;
            program.AddTopLevelDeclaration(func);
            program.AddTopLevelDeclaration(axiom);
            axioms.Add(axiom);

            var call = new NAryExpr(Token.NoToken, new FunctionCall(func), originalVars.Select(v => new IdentifierExpr(Token.NoToken, v)).ToList <Expr>());

            call.Type           = expr.Type;
            call.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
            return(call);
        }
Example #2
0
        public override Cmd VisitCallCmd(CallCmd node)
        {
            var result = base.VisitCallCmd(node);

            var oldProc = programInCachedSnapshot.FindProcedure(node.Proc.Name);

            if (oldProc != null &&
                oldProc.DependencyChecksum != node.Proc.DependencyChecksum &&
                node.AssignedAssumptionVariable == null)
            {
                var  before = new List <Cmd>();
                var  beforePreconditionCheck = new List <Cmd>();
                var  after       = new List <Cmd>();
                var  axioms      = new List <Axiom>();
                Expr assumedExpr = new LiteralExpr(Token.NoToken, false);
                // TODO(wuestholz): Try out two alternatives: only do this for low priority implementations or not at all.
                var canUseSpecs = DependencyCollector.CanExpressOldSpecs(oldProc, Program);
                if (canUseSpecs && oldProc.SignatureEquals(node.Proc))
                {
                    var desugaring = node.Desugaring;
                    Contract.Assert(desugaring != null);
                    var precond = node.CheckedPrecondition(oldProc, Program, e => FunctionExtractor.Extract(e, Program, axioms));
                    if (precond != null)
                    {
                        var assume = new AssumeCmd(node.tok, precond,
                                                   new QKeyValue(Token.NoToken, "precondition_previous_snapshot", new List <object>(), null));
                        assume.IrrelevantForChecksumComputation = true;
                        beforePreconditionCheck.Add(assume);
                    }

                    var unmods = node.UnmodifiedBefore(oldProc);
                    var eqs    = new List <Expr>();
                    foreach (var unmod in unmods)
                    {
                        var oldUnmod = new LocalVariable(Token.NoToken,
                                                         new TypedIdent(Token.NoToken, string.Format("{0}##old##{1}", unmod.Name, FreshTemporaryVariableName),
                                                                        unmod.Type));
                        var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, oldUnmod));
                        var rhs = new IdentifierExpr(Token.NoToken, unmod.Decl);
                        var cmd = new AssignCmd(Token.NoToken, new List <AssignLhs> {
                            lhs
                        }, new List <Expr> {
                            rhs
                        });
                        cmd.IrrelevantForChecksumComputation = true;
                        before.Add(cmd);
                        var eq = LiteralExpr.Eq(new IdentifierExpr(Token.NoToken, oldUnmod),
                                                new IdentifierExpr(Token.NoToken, unmod.Decl));
                        eq.Type           = Type.Bool;
                        eq.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
                        eqs.Add(eq);
                    }

                    var mods     = node.ModifiedBefore(oldProc);
                    var oldSubst = new Dictionary <Variable, Expr>();
                    foreach (var mod in mods)
                    {
                        var oldMod = new LocalVariable(Token.NoToken,
                                                       new TypedIdent(Token.NoToken, string.Format("{0}##old##{1}", mod.Name, FreshTemporaryVariableName),
                                                                      mod.Type));
                        oldSubst[mod.Decl] = new IdentifierExpr(Token.NoToken, oldMod);
                        var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, oldMod));
                        var rhs = new IdentifierExpr(Token.NoToken, mod.Decl);
                        var cmd = new AssignCmd(Token.NoToken, new List <AssignLhs> {
                            lhs
                        }, new List <Expr> {
                            rhs
                        });
                        cmd.IrrelevantForChecksumComputation = true;
                        before.Add(cmd);
                    }

                    assumedExpr = node.Postcondition(oldProc, eqs, oldSubst, Program,
                                                     e => FunctionExtractor.Extract(e, Program, axioms));
                    if (assumedExpr == null)
                    {
                        assumedExpr = new LiteralExpr(Token.NoToken, true);
                    }
                }

                if (assumedExpr != null)
                {
                    var lv = new LocalVariable(Token.NoToken,
                                               new TypedIdent(Token.NoToken, string.Format("a##cached##{0}", FreshAssumptionVariableName), Type.Bool),
                                               new QKeyValue(Token.NoToken, "assumption", new List <object>(), null));
                    node.AssignedAssumptionVariable = lv;
                    currentImplementation.InjectAssumptionVariable(lv, !canUseSpecs);
                    var lhs     = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, lv));
                    var rhs     = LiteralExpr.And(new IdentifierExpr(Token.NoToken, lv), assumedExpr);
                    var assumed = new AssignCmd(node.tok, new List <AssignLhs> {
                        lhs
                    }, new List <Expr> {
                        rhs
                    });
                    assumed.IrrelevantForChecksumComputation = true;
                    after.Add(assumed);
                }

                node.ExtendDesugaring(before, beforePreconditionCheck, after);
                if (CommandLineOptions.Clo.TraceCachingForTesting || CommandLineOptions.Clo.TraceCachingForBenchmarking)
                {
                    using (var tokTxtWr = new TokenTextWriter("<console>", Console.Out, false, false))
                    {
                        var loc = node.tok != null && node.tok != Token.NoToken
              ? string.Format("{0}({1},{2})", node.tok.filename, node.tok.line, node.tok.col)
              : "<unknown location>";
                        Console.Out.WriteLine("Processing call to procedure {0} in implementation {1} (at {2}):", node.Proc.Name,
                                              currentImplementation.Name, loc);
                        foreach (var a in axioms)
                        {
                            Console.Out.Write("  >>> added axiom: ");
                            a.Expr.Emit(tokTxtWr);
                            Console.Out.WriteLine();
                        }

                        foreach (var b in before)
                        {
                            Console.Out.Write("  >>> added before: ");
                            b.Emit(tokTxtWr, 0);
                        }

                        foreach (var b in beforePreconditionCheck)
                        {
                            Console.Out.Write("  >>> added before precondition check: ");
                            b.Emit(tokTxtWr, 0);
                        }

                        foreach (var a in after)
                        {
                            Console.Out.Write("  >>> added after: ");
                            a.Emit(tokTxtWr, 0);
                        }
                    }
                }
            }

            return(result);
        }
Example #3
0
        public Implementation Inject(Implementation implementation, Program programInCachedSnapshot)
        {
            Contract.Requires(implementation != null && programInCachedSnapshot != null);

            this.programInCachedSnapshot = programInCachedSnapshot;
            assumptionVariableCount      = 0;
            temporaryVariableCount       = 0;
            currentImplementation        = implementation;

            #region Introduce explict assumption about the precondition.

            var oldProc = programInCachedSnapshot.FindProcedure(currentImplementation.Proc.Name);
            if (oldProc != null &&
                oldProc.DependencyChecksum != currentImplementation.Proc.DependencyChecksum &&
                currentImplementation.ExplicitAssumptionAboutCachedPrecondition == null)
            {
                var  axioms      = new List <Axiom>();
                var  after       = new List <Cmd>();
                Expr assumedExpr = new LiteralExpr(Token.NoToken, false);
                var  canUseSpecs = DependencyCollector.CanExpressOldSpecs(oldProc, Program, true);
                if (canUseSpecs && oldProc.SignatureEquals(currentImplementation.Proc))
                {
                    var always = Substituter.SubstitutionFromHashtable(currentImplementation.GetImplFormalMap(), true,
                                                                       currentImplementation.Proc);
                    var forOld  = Substituter.SubstitutionFromHashtable(new Dictionary <Variable, Expr>());
                    var clauses = oldProc.Requires.Select(r =>
                                                          Substituter.FunctionCallReresolvingApply(always, forOld, r.Condition, Program));
                    var conj = Expr.And(clauses, true);
                    assumedExpr = conj != null
            ? FunctionExtractor.Extract(conj, Program, axioms)
            : new LiteralExpr(Token.NoToken, true);
                }

                if (assumedExpr != null)
                {
                    var lv = new LocalVariable(Token.NoToken,
                                               new TypedIdent(Token.NoToken, string.Format("a##cached##{0}", FreshAssumptionVariableName), Type.Bool),
                                               new QKeyValue(Token.NoToken, "assumption", new List <object>(), null));
                    currentImplementation.InjectAssumptionVariable(lv, !canUseSpecs);
                    var lhs     = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, lv));
                    var rhs     = LiteralExpr.And(new IdentifierExpr(Token.NoToken, lv), assumedExpr);
                    var assumed = new AssignCmd(currentImplementation.tok, new List <AssignLhs> {
                        lhs
                    }, new List <Expr> {
                        rhs
                    });
                    assumed.IrrelevantForChecksumComputation = true;
                    currentImplementation.ExplicitAssumptionAboutCachedPrecondition = assumed;
                    after.Add(assumed);
                }

                if (CommandLineOptions.Clo.TraceCachingForTesting || CommandLineOptions.Clo.TraceCachingForBenchmarking)
                {
                    using (var tokTxtWr = new TokenTextWriter("<console>", Console.Out, false, false))
                    {
                        var loc = currentImplementation.tok != null && currentImplementation.tok != Token.NoToken
              ? string.Format("{0}({1},{2})", currentImplementation.tok.filename, currentImplementation.tok.line,
                              currentImplementation.tok.col)
              : "<unknown location>";
                        Console.Out.WriteLine("Processing implementation {0} (at {1}):", currentImplementation.Name, loc);
                        foreach (var a in axioms)
                        {
                            Console.Out.Write("  >>> added axiom: ");
                            a.Expr.Emit(tokTxtWr);
                            Console.Out.WriteLine();
                        }

                        foreach (var b in after)
                        {
                            Console.Out.Write("  >>> added after assuming the current precondition: ");
                            b.Emit(tokTxtWr, 0);
                        }
                    }
                }
            }

            #endregion

            var result = VisitImplementation(currentImplementation);
            currentImplementation        = null;
            this.programInCachedSnapshot = null;
            return(result);
        }
    public static Expr Extract(Expr expr, Program program, List<Axiom> axioms)
    {
      Contract.Requires(expr != null && program != null && !program.TopLevelDeclarationsAreFrozen && axioms != null);
      
      if (expr is LiteralExpr)
      {
        return expr;
      }

      var extractor = new FunctionExtractor();

      var body = extractor.VisitExpr(expr);

      var name = program.FreshExtractedFunctionName();
      var originalVars = extractor.Substitutions.Keys.ToList();
      var formalInArgs = originalVars.Select(v => new Formal(Token.NoToken, new TypedIdent(Token.NoToken, extractor.Substitutions[v].Name, extractor.Substitutions[v].TypedIdent.Type), true)).ToList<Variable>();
      var formalOutArg = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, name + "$result$", expr.Type), false);
      var func = new Function(Token.NoToken, name, formalInArgs, formalOutArg);
      func.AddAttribute("never_pattern");

      var boundVars = originalVars.Select(k => extractor.Substitutions[k]);
      var axiomCall = new NAryExpr(Token.NoToken, new FunctionCall(func), boundVars.Select(b => new IdentifierExpr(Token.NoToken, b)).ToList<Expr>());
      axiomCall.Type = expr.Type;
      axiomCall.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
      var eq = LiteralExpr.Eq(axiomCall, body);
      eq.Type = body.Type;
      eq.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
      if (0 < formalInArgs.Count)
      {
        var forallExpr = new ForallExpr(Token.NoToken, boundVars.ToList<Variable>(), new Trigger(Token.NoToken, true, new List<Expr> { axiomCall }), eq);
        body = forallExpr;
        forallExpr.Attributes = new QKeyValue(Token.NoToken, "weight", new List<object> { new LiteralExpr(Token.NoToken, Basetypes.BigNum.FromInt(30)) }, null);
        body.Type = Type.Bool;
      }
      else
      {
        body = eq;
      }

      var axiom = new Axiom(Token.NoToken, body);
      func.DefinitionAxiom = axiom;
      program.AddTopLevelDeclaration(func);
      program.AddTopLevelDeclaration(axiom);
      axioms.Add(axiom);

      var call = new NAryExpr(Token.NoToken, new FunctionCall(func), originalVars.Select(v => new IdentifierExpr(Token.NoToken, v)).ToList<Expr>());
      call.Type = expr.Type;
      call.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
      return call;
    }