예제 #1
0
 bool RewriteMatchingLoop()
 {
     if (expr is QuantifierExpr)
     {
         QuantifierExpr    quantifier = (QuantifierExpr)expr;
         var               l          = new List <QuantifierWithTriggers>();
         List <Expression> splits     = new List <Expression>();
         bool              rewritten  = false;
         foreach (var q in quantifiers)
         {
             if (TriggerUtils.NeedsAutoTriggers(q.quantifier) && TriggerUtils.WantsMatchingLoopRewrite(q.quantifier))
             {
                 var matchingLoopRewriter = new MatchingLoopRewriter();
                 var qq = matchingLoopRewriter.RewriteMatchingLoops(q);
                 splits.Add(qq);
                 l.Add(new QuantifierWithTriggers(qq));
                 rewritten = true;
             }
             else
             {
                 // don't rewrite the quantifier if we are not auto generate triggers.
                 // This is because rewriting introduces new boundvars and will cause
                 // user provided triggers not mention all boundvars
                 splits.Add(q.quantifier);
                 l.Add(q);
             }
         }
         if (rewritten)
         {
             quantifier.SplitQuantifier = splits;
             quantifiers = l;
             return(true);
         }
     }
     return(false);
 }
예제 #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          = DafnyOptions.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);
            }
        }