internal static IEnumerable <Expression> SplitQuantifier(ComprehensionExpr quantifier)
        {
            var body   = quantifier.Term;
            var binary = body as BinaryExpr;

            if (quantifier is ForallExpr)
            {
                IEnumerable <Expression> stream;
                if (binary != null && (binary.Op == BinaryExpr.Opcode.Imp || binary.Op == BinaryExpr.Opcode.Or))
                {
                    stream = SplitAndStich(binary, BinaryExpr.Opcode.And);
                }
                else
                {
                    stream = SplitExpr(body, BinaryExpr.Opcode.And);
                }
                foreach (var e in stream)
                {
                    var tok = new NestedToken(quantifier.tok, e.tok);
                    yield return(new ForallExpr(tok, ((ForallExpr)quantifier).TypeArgs, quantifier.BoundVars, quantifier.Range, e, TriggerUtils.CopyAttributes(quantifier.Attributes))
                    {
                        Type = quantifier.Type, Bounds = quantifier.Bounds
                    });
                }
            }
            else if (quantifier is ExistsExpr)
            {
                IEnumerable <Expression> stream;
                if (binary != null && binary.Op == BinaryExpr.Opcode.And)
                {
                    stream = SplitAndStich(binary, BinaryExpr.Opcode.Or);
                }
                else
                {
                    stream = SplitExpr(body, BinaryExpr.Opcode.Or);
                }
                foreach (var e in stream)
                {
                    var tok = new NestedToken(quantifier.tok, e.tok);
                    yield return(new ExistsExpr(tok, ((ExistsExpr)quantifier).TypeArgs, quantifier.BoundVars, quantifier.Range, e, TriggerUtils.CopyAttributes(quantifier.Attributes))
                    {
                        Type = quantifier.Type, Bounds = quantifier.Bounds
                    });
                }
            }
            else
            {
                yield return(quantifier);
            }
        }
        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);
        }
Esempio n. 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;
     }
 }