internal QuantifiersCollection(ComprehensionExpr expr, IEnumerable <ComprehensionExpr> quantifiers, ErrorReporter reporter) { Contract.Requires(quantifiers.All(q => !(q is QuantifierExpr) || ((QuantifierExpr)q).SplitQuantifier == null)); this.reporter = reporter; this.expr = expr; this.quantifiers = quantifiers.Select(q => new QuantifierWithTriggers(q)).ToList(); }
private static bool AllowsSplitting(ComprehensionExpr quantifier) { // allow split if attributes doesn't contains "split" or it is "split: true" and it is not an empty QuantifierExpr (boundvar.count>0) bool splitAttr = true; return((!Attributes.ContainsBool(quantifier.Attributes, "split", ref splitAttr) || splitAttr) && (quantifier.BoundVars.Count > 0)); }
private static bool ShallowEq(ComprehensionExpr expr1, ComprehensionExpr expr2) { if (!TriggerUtils.SameLists(expr1.BoundVars, expr2.BoundVars, SameBoundVar) || !ShallowSameAttributes(expr1.Attributes, expr2.Attributes) || // Filled in during resolution: !SameLists(expr1.Bounds, expr2.Bounds, ReferenceCompare) || // !SameLists(expr1.MissingBounds, expr2.MissingBounds, SameBoundVar) || !TriggerUtils.SameNullity(expr1.Range, expr2.Range)) //TODO Check { return(false); } if (expr1 is LambdaExpr && expr2 is LambdaExpr) { return(ShallowEq((LambdaExpr)expr1, (LambdaExpr)expr2)); } else if (expr1 is MapComprehension && expr2 is MapComprehension) { return(ShallowEq((MapComprehension)expr1, (MapComprehension)expr2)); } else if (expr1 is SetComprehension && expr2 is SetComprehension) { return(ShallowEq((SetComprehension)expr1, (SetComprehension)expr2)); } else if (expr1 is QuantifierExpr && expr2 is QuantifierExpr) { return(ShallowEq((QuantifierExpr)expr1, (QuantifierExpr)expr2)); } else { return(false); // ComprehensionExpr is abstract } }
internal static bool WantsAutoTriggers(ComprehensionExpr quantifier) { Contract.Requires(!(quantifier is QuantifierExpr) || ((QuantifierExpr)quantifier).SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier bool wantsAutoTriggers = true; return(!Attributes.ContainsBool(quantifier.Attributes, "autotriggers", ref wantsAutoTriggers) || wantsAutoTriggers); }
internal static bool WantsMatchingLoopRewrite(ComprehensionExpr quantifier) { Contract.Requires(!(quantifier is QuantifierExpr) || ((QuantifierExpr)quantifier).SplitQuantifier == null); bool wantsMatchingLoopRewrite = true; return((!Attributes.ContainsBool(quantifier.Attributes, "matchinglooprewrite", ref wantsMatchingLoopRewrite) || wantsMatchingLoopRewrite) && WantsAutoTriggers(quantifier)); }
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, CopyAttributes(quantifier.Attributes)) { Type = quantifier.Type }; } } 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, CopyAttributes(quantifier.Attributes)) { Type = quantifier.Type }; } } else { yield return quantifier; } }
internal IEnumerable <TriggerMatch> LoopingSubterms(ComprehensionExpr quantifier) { Contract.Requires(!(quantifier is QuantifierExpr) || ((QuantifierExpr)quantifier).SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier var matchingSubterms = this.MatchingSubterms(quantifier); var boundVars = new HashSet <BoundVar>(quantifier.BoundVars); return(matchingSubterms.Where(tm => tm.CouldCauseLoops(Terms, boundVars))); }
private Expression QuantifiersToExpression(IToken tok, BinaryExpr.ResolvedOpcode op, List <ComprehensionExpr> expressions) { var expr = expressions[0].Term; for (int i = 1; i < expressions.Count; i++) { expr = new BinaryExpr(tok, op, expr, expressions[i].Term); } return(expr); }
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 }); } } 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 }); } } else { yield return(quantifier); } }
private void ExprVars(Expression e) { Contract.Requires(_vars != null); Contract.Requires(e != null); var expr = e as ComprehensionExpr; if (expr != null) { ComprehensionExpr c = expr; foreach (BoundVar bv in c.BoundVars) { _vars.Add(bv.Name); } } }
public override void Visit(ComprehensionExpr o) { var name = "bounded-expression-ghost-" + o.tok.line; IToken endToken = new Token(o.tok.line, int.MaxValue - 1024); var symbol = CreateSymbol( name: name, kind: Kind.BlockScope, positionAsToken: o.tok, bodyStartPosAsToken: o.tok, bodyEndPosAsToken: endToken, isDeclaration: true, declarationSymbol: null, addUsageAtDeclaration: false, canHaveChildren: true, canBeUsed: false ); SetScope(symbol); }
/// <summary> /// Collect terms in the body of the subexpressions of the argument that look like quantifiers. The results of this function can contain duplicate terms. /// </summary> internal List <TriggerTerm> CollectTriggers(ComprehensionExpr quantifier) { Contract.Requires(!(quantifier is QuantifierExpr) || ((QuantifierExpr)quantifier).SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier // NOTE: We could check for existing trigger attributes and return that instead return(Annotate(quantifier).PrivateTerms); }
private TriggerAnnotation AnnotateComprehensionExpr(ComprehensionExpr expr) { var terms = CollectExportedCandidates(expr); return(new TriggerAnnotation(true, CollectVariables(expr), terms, OnlyPrivateCandidates(terms, expr.BoundVars))); }
internal List <TriggerMatch> MatchingSubterms(ComprehensionExpr quantifier) { Contract.Requires(!(quantifier is QuantifierExpr) || ((QuantifierExpr)quantifier).SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier return(Terms.SelectMany(term => quantifier.SubexpressionsMatchingTrigger(term.Expr)).Deduplicate(TriggerMatch.Eq)); }
internal static bool NeedsAutoTriggers(ComprehensionExpr quantifier) { Contract.Requires(!(quantifier is QuantifierExpr) || ((QuantifierExpr)quantifier).SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier return(!Attributes.Contains(quantifier.Attributes, "trigger") && WantsAutoTriggers(quantifier)); }
public override void Visit(ComprehensionExpr o) { }
internal static bool AllowsMatchingLoops(ComprehensionExpr quantifier) { Contract.Requires(!(quantifier is QuantifierExpr) || ((QuantifierExpr)quantifier).SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier // This is different from nowarn: it won't remove loops at all, even if another trigger is available. return(Attributes.Contains(quantifier.Attributes, "matchingloop")); }
public override void Leave(ComprehensionExpr o) { }
internal static IEnumerable <TriggerMatch> SubexpressionsMatchingTrigger(this ComprehensionExpr quantifier, Expression trigger) { return(quantifier.AllSubExpressions(true, true, true) .Select(e => TriggerUtils.PrepareExprForInclusionInTrigger(e).MatchAgainst(trigger, quantifier.BoundVars, e)) .Where(e => e.HasValue).Select(e => e.Value)); }
public override void Leave(ComprehensionExpr o) { JumpUpInScope(); }
internal QuantifierWithTriggers(ComprehensionExpr quantifier) { this.quantifier = quantifier; this.RejectedCandidates = new List <TriggerCandidate>(); }
public virtual void Visit(ComprehensionExpr comprehensionExpression) { }
private static bool AllowsSplitting(ComprehensionExpr quantifier) { // allow split if attributes doesn't contains "split" or it is "split: true" and it is not an empty ComprehensionExpr (boundvar.count>0) bool splitAttr = true; return (!Attributes.ContainsBool(quantifier.Attributes, "split", ref splitAttr) || splitAttr) && (quantifier.BoundVars.Count > 0); }