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); }
// 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; } }