コード例 #1
0
        public QuantifierExpr RewriteMatchingLoops(QuantifierWithTriggers q)
        {
            // rewrite quantifier to avoid matching loops
            // before:
            //    assert forall i :: 0 <= i < a.Length-1 ==> a[i] <= a[i+1];
            // after:
            //    assert forall i,j :: j == i+1 ==> 0 <= i < a.Length-1 ==> a[i] <= a[j];
            substMap = new List <Tuple <Expression, IdentifierExpr> >();
            foreach (var m in q.LoopingMatches)
            {
                var e = m.OriginalExpr;
                if (TriggersCollector.IsPotentialTriggerCandidate(e) && triggersCollector.IsTriggerKiller(e))
                {
                    foreach (var sub in e.SubExpressions)
                    {
                        if (triggersCollector.IsTriggerKiller(sub) && (!TriggersCollector.IsPotentialTriggerCandidate(sub)))
                        {
                            var entry = substMap.Find(x => ExprExtensions.ExpressionEq(sub, x.Item1));
                            if (entry == null)
                            {
                                var newBv = new BoundVar(sub.tok, "_t#" + substMap.Count, sub.Type);
                                var ie    = new IdentifierExpr(sub.tok, newBv.Name);
                                ie.Var  = newBv;
                                ie.Type = newBv.Type;
                                substMap.Add(new Tuple <Expression, IdentifierExpr>(sub, ie));
                            }
                        }
                    }
                }
            }

            var expr = (QuantifierExpr)q.quantifier;

            if (substMap.Count > 0)
            {
                var s = new Translator.ExprSubstituter(substMap);
                expr = s.Substitute(q.quantifier) as QuantifierExpr;
            }
            else
            {
                // make a copy of the expr
                if (expr is ForallExpr)
                {
                    expr = new ForallExpr(expr.tok, expr.TypeArgs, expr.BoundVars, expr.Range, expr.Term, TriggerUtils.CopyAttributes(expr.Attributes))
                    {
                        Type = expr.Type, Bounds = expr.Bounds
                    };
                }
                else
                {
                    expr = new ExistsExpr(expr.tok, expr.TypeArgs, expr.BoundVars, expr.Range, expr.Term, TriggerUtils.CopyAttributes(expr.Attributes))
                    {
                        Type = expr.Type, Bounds = expr.Bounds
                    };
                }
            }
            return(expr);
        }
コード例 #2
0
        private void CommitOne(QuantifierWithTriggers q, bool addHeader)
        {
            var  errorLevel       = ErrorLevel.Info;
            var  msg              = new StringBuilder();
            var  indent           = addHeader ? "  " : "";
            bool suppressWarnings = Attributes.Contains(q.quantifier.Attributes, "nowarn");

            if (!TriggerUtils.NeedsAutoTriggers(q.quantifier)) // NOTE: split and autotriggers attributes are passed down to Boogie
            {
                var extraMsg = TriggerUtils.WantsAutoTriggers(q.quantifier) ? "" : " Note that {:autotriggers false} can cause instabilities. Consider using {:nowarn}, {:matchingloop} (not great either), or a manual trigger instead.";
                msg.AppendFormat("Not generating triggers for \"{0}\".{1}", Printer.ExprToString(q.quantifier.Term), extraMsg).AppendLine();
            }
            else
            {
                if (addHeader)
                {
                    msg.AppendFormat("For expression \"{0}\":", Printer.ExprToString(q.quantifier.Term)).AppendLine();
                }

                foreach (var candidate in q.Candidates)
                {
                    q.quantifier.Attributes = new Attributes("trigger", candidate.Terms.Select(t => t.Expr).ToList(), q.quantifier.Attributes);
                }

                AddTriggersToMessage("Selected triggers:", q.Candidates, msg, indent);
                AddTriggersToMessage("Rejected triggers:", q.RejectedCandidates, msg, indent, true);

#if QUANTIFIER_WARNINGS
                var WARN_TAG          = ArmadaOptions.O.UnicodeOutput ? "⚠ " : "/!\\ ";
                var WARN_TAG_OVERRIDE = suppressWarnings ? "(Suppressed warning) " : WARN_TAG;
                var WARN_LEVEL        = suppressWarnings ? ErrorLevel.Info : ErrorLevel.Warning;
                var WARN = indent + WARN_TAG_OVERRIDE;
                if (!q.CandidateTerms.Any())
                {
                    errorLevel = WARN_LEVEL;
                    msg.Append(WARN).AppendLine("No terms found to trigger on.");
                }
                else if (!q.Candidates.Any())
                {
                    errorLevel = WARN_LEVEL;
                    msg.Append(WARN).AppendLine("No trigger covering all quantified variables found.");
                }
                else if (!q.CouldSuppressLoops && !q.AllowsLoops)
                {
                    errorLevel = WARN_LEVEL;
                    msg.Append(WARN).AppendLine("Suppressing loops would leave this expression without triggers.");
                }
                else if (suppressWarnings)
                {
                    errorLevel = ErrorLevel.Warning;
                    msg.Append(indent).Append(WARN_TAG).AppendLine("There is no warning here to suppress.");
                }
#endif
            }

            if (msg.Length > 0)
            {
                var msgStr = msg.ToString().TrimEnd("\r\n ".ToCharArray());
                reporter.Message(MessageSource.Rewriter, errorLevel, q.quantifier.tok, msgStr);
            }
        }
コード例 #3
0
 // group split quantifier by what triggers they got, and merged them back into one quantifier.
 private void CombineSplitQuantifier()
 {
     if (quantifiers.Count > 1)
     {
         List <QuantifierGroup> groups = new List <QuantifierGroup>();
         groups.Add(new QuantifierGroup(quantifiers[0], new List <ComprehensionExpr> {
             quantifiers[0].quantifier
         }));
         for (int i = 1; i < quantifiers.Count; i++)
         {
             bool found = false;
             for (int j = 0; j < groups.Count; j++)
             {
                 if (HasSameTriggers(quantifiers[i], groups[j].quantifier))
                 {
                     // belong to the same group
                     groups[j].expressions.Add(quantifiers[i].quantifier);
                     found = true;
                     break;
                 }
             }
             if (!found)
             {
                 // start a new group
                 groups.Add(new QuantifierGroup(quantifiers[i], new List <ComprehensionExpr> {
                     quantifiers[i].quantifier
                 }));
             }
         }
         if (groups.Count == quantifiers.Count)
         {
             // have the same number of splits, so no splits are combined.
             return;
         }
         // merge expressions in each group back to one quantifier.
         List <QuantifierWithTriggers> list   = new List <QuantifierWithTriggers>();
         List <Expression>             splits = new List <Expression>();
         foreach (var group in groups)
         {
             QuantifierWithTriggers q = group.quantifier;
             if (q.quantifier is ForallExpr)
             {
                 ForallExpr quantifier = (ForallExpr)q.quantifier;
                 Expression expr       = QuantifiersToExpression(quantifier.tok, BinaryExpr.ResolvedOpcode.And, group.expressions);
                 q.quantifier = new ForallExpr(quantifier.tok, quantifier.TypeArgs, quantifier.BoundVars, quantifier.Range, expr, TriggerUtils.CopyAttributes(quantifier.Attributes))
                 {
                     Type = quantifier.Type, Bounds = quantifier.Bounds
                 };
             }
             else if (q.quantifier is ExistsExpr)
             {
                 ExistsExpr quantifier = (ExistsExpr)q.quantifier;
                 Expression expr       = QuantifiersToExpression(quantifier.tok, BinaryExpr.ResolvedOpcode.Or, group.expressions);
                 q.quantifier = new ExistsExpr(quantifier.tok, quantifier.TypeArgs, quantifier.BoundVars, quantifier.Range, expr, TriggerUtils.CopyAttributes(quantifier.Attributes))
                 {
                     Type = quantifier.Type, Bounds = quantifier.Bounds
                 };
             }
             list.Add(q);
             splits.Add(q.quantifier);
         }
         this.quantifiers = list;
         Contract.Assert(this.expr is QuantifierExpr); // only QuantifierExpr has SplitQuantifier
         ((QuantifierExpr)this.expr).SplitQuantifier = splits;
     }
 }
コード例 #4
0
 private bool HasSameTriggers(QuantifierWithTriggers one, QuantifierWithTriggers other)
 {
     return(TriggerUtils.SameLists(one.Candidates, other.Candidates, SameTriggerCandidate));
 }
コード例 #5
0
 public QuantifierGroup(QuantifierWithTriggers q, List <ComprehensionExpr> expressions)
 {
     this.quantifier  = q;
     this.expressions = expressions;
 }