internal static bool WantsAutoTriggers(QuantifierExpr quantifier) { Contract.Requires(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); }
// need to push bound type variables public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) { if (!(node is ForallExpr || node is ExistsExpr)) { throw new ProofGenUnexpectedStateException(GetType(), "can only handle forall and exists quantifiers"); } //Quantifers with multiple bound variables are desugared into multiple quantifiers expressions with single variables foreach (var boundTyVar in node.TypeParameters) { tyVarTranslation.AddBoundVariable(boundTyVar); } var numTyVarBefore = tyVarTranslation.NumBoundVariables(); Visit(node.Body); if (numTyVarBefore != tyVarTranslation.NumBoundVariables()) { throw new ProofGenUnexpectedStateException(GetType(), "quantifier levels not the same before and after"); } for (var i = node.TypeParameters.Count - 1; i >= 0; i--) { tyVarTranslation.DropLastBoundVariable(); } return(node); }
private static bool ShallowEq(QuantifierExpr expr1, QuantifierExpr expr2) { if (!TriggerUtils.SameNullity(expr1.SplitQuantifier, expr2.SplitQuantifier)) { return(false); } if (expr1.SplitQuantifier != null && expr2.SplitQuantifier != null) { return(ShallowEq_Top(expr1.SplitQuantifierExpression, expr2.SplitQuantifierExpression)); } if (expr1.TypeArgs.Count != expr2.TypeArgs.Count || !TriggerUtils.SameNullity(expr1.Range, expr2.Range)) { return(false); } if (expr1 is ExistsExpr && expr2 is ExistsExpr) { return(ShallowEq((ExistsExpr)expr1, (ExistsExpr)expr2)); } else if (expr1 is ForallExpr && expr2 is ForallExpr) { return(ShallowEq((ForallExpr)expr1, (ForallExpr)expr2)); } else { return(false); } }
private static bool AllowsSplitting(QuantifierExpr 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)); }
internal IEnumerable <TriggerMatch> LoopingSubterms(QuantifierExpr quantifier) { Contract.Requires(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 bool IsForall(QuantifierExpr quantifierExpr) { if (quantifierExpr is ForallExpr) { return(true); } if (quantifierExpr is ExistsExpr) { return(false); } throw new ProofGenUnexpectedStateException(GetType(), "Unexpected quantifier"); }
// This is necessary because the root of the Tree might be a QuantifierExpr public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) { bool goDeeper = CountExpr(node); if (goDeeper) { return(base.VisitQuantifierExpr(node)); } else { return(node); } }
public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) { if (node.TypeParameters.Count > 0) { _result = true; _hasTypeQuantification = true; } _withinNumQuantifier++; Visit(node._Body); _withinNumQuantifier--; return(node); }
public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) { var oldE = existentialExpr; if (node is ExistsExpr) { existentialExpr = (node as ExistsExpr); } node = base.VisitQuantifierExpr(node); existentialExpr = oldE; return(node); }
internal static IEnumerable <Expression> SplitQuantifier(QuantifierExpr 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, 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, quantifier.TypeArgs, quantifier.BoundVars, quantifier.Range, e, CopyAttributes(quantifier.Attributes)) { Type = quantifier.Type }); } } else { yield return(quantifier); } }
// Do not dualise quantified variables public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) { List <Variable> vs = node.Dummies; foreach (Variable dummy in vs) { quantifiedVars.Add(dummy); } base.VisitQuantifierExpr(node); foreach (Variable dummy in vs) { quantifiedVars.Remove(dummy); } return(node); }
public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) { if (!(node is ForallExpr || node is ExistsExpr)) { throw new ProofGenUnexpectedStateException(GetType(), "can only handle forall and exists quantifiers"); } var isForall = IsForall(node); //Quantifers with multiple bound variables are desugared into multiple quantifiers expressions with single variables foreach (var boundVar in node.Dummies) { boogieVarTranslation.VarTranslation.AddBoundVariable(boundVar); } foreach (var boundTyVar in node.TypeParameters) { boogieVarTranslation.TypeVarTranslation.AddBoundVariable(boundTyVar); } var numValVarBefore = boogieVarTranslation.VarTranslation.NumBoundVariables(); var numTyVarBefore = boogieVarTranslation.TypeVarTranslation.NumBoundVariables(); var result = Translate(node.Body); if (numValVarBefore != boogieVarTranslation.VarTranslation.NumBoundVariables() || numTyVarBefore != boogieVarTranslation.TypeVarTranslation.NumBoundVariables()) { throw new ProofGenUnexpectedStateException(GetType(), "quantifier levels not the same before and after"); } for (var i = node.Dummies.Count - 1; i >= 0; i--) { boogieVarTranslation.VarTranslation.DropLastBoundVariable(); var boundVar = node.Dummies[i]; var boundVarType = typeIsaVisitor.Translate(boundVar.TypedIdent.Type); result = IsaBoogieTerm.Quantifier(isForall, boundVarType, result); } for (var i = node.TypeParameters.Count - 1; i >= 0; i--) { boogieVarTranslation.TypeVarTranslation.DropLastBoundVariable(); result = IsaBoogieTerm.TypeQuantifier(isForall, result); } ReturnResult(result); return(node); }
//////////////////////////////////////////////////////////////////////////////////// //TODO:Check if we get functions here private Term makeExpression(QuantifierExpr qe, bool old) { Term e = null; { List <Logic.Variable> quantifiedVariables = new List <Logic.Variable>(); foreach (Microsoft.Boogie.Variable bv in qe.Dummies) { quantifiedVariables.Add(new Logic.Basic.Variable(bv.TypedIdent.Name)); } foreach (var v in quantifiedVariables) { boundVariables.Add(v.name, v); } e = makeExpression(qe.Body, old); foreach (var v in quantifiedVariables) { boundVariables.Remove(v.name); } } { Logic.Quantifier q = makeQuantifier(qe.Kind); for (int i = qe.Dummies.Length - 1; i >= 0; i--) { Microsoft.Boogie.Variable v = qe.Dummies[i]; Logic.Sort ls = new Logic.Boogie.BoogieSort(v.TypedIdent.Type); Logic.Variable lv = new Logic.Boogie.BoogieVariable(v); e = new Boogie.QuantifiedExpression(qe, q, lv, ls, e); } } { Logic.TypeQuantifier tq = makeTypeQuantifier(qe.Kind); for (int i = qe.TypeParameters.Length - 1; i >= 0; i--) { Microsoft.Boogie.TypeVariable btv = qe.TypeParameters[i]; Logic.TypeVariable tv = new Logic.Boogie.TypeVariable(btv); e = new Boogie.QuantifiedTypeExpression(qe, tq, tv, e); } } return(e); }
/////////////////////////////////////////////////////////// public BoogieQuantifiedTypeExpression( QuantifierExpr boogieExpression, TypeQuantifier quantifier, TypeVariable variable, Expression expression, List <Expression> triggers, string attributes ) : base( quantifier, variable, expression, triggers, attributes ) { Debug.Assert(boogieExpression != null); boogieQTExpression = boogieExpression; }
/////////////////////////////////////////////////////////// public BoogieQuantifiedExpression( Scope s, QuantifierExpr boogieExpression, Quantifier quantifier, BoundVariable variable, Expression expression, IEnumerable <IEnumerable <Expression> > triggers, string attributes ) : base( s, quantifier, variable, expression, triggers, attributes ) { Debug.Assert(boogieExpression != null); boogieQExpression = boogieExpression; }
bool RewriteMatchingLoop() { if (expr is QuantifierExpr && TriggerUtils.WantsMatchingLoopRewrite((QuantifierExpr)expr)) { QuantifierExpr quantifier = (QuantifierExpr)expr; var l = new List <QuantifierWithTriggers>(); // only split quantifier expr now. List <Expression> splits = new List <Expression>(); foreach (var q in quantifiers) { var matchingLoopRewriter = new MatchingLoopRewriter(); var qq = matchingLoopRewriter.RewriteMatchingLoops(q); splits.Add(qq); l.Add(new QuantifierWithTriggers(qq)); } quantifier.SplitQuantifier = splits; quantifiers = l; return(true); } return(false); }
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); }
internal static IEnumerable <TriggerMatch> SubexpressionsMatchingTrigger(this QuantifierExpr quantifier, Expression trigger) { return(quantifier.AllSubExpressions(true, true) .Select(e => TriggerUtils.PrepareExprForInclusionInTrigger(e).MatchAgainst(trigger, quantifier.BoundVars, e)) .Where(e => e.HasValue).Select(e => e.Value)); }
List <Expression> GenerateAutoReqs(Expression expr, Function parent) { List <Expression> reqs = new List <Expression>(); Func <Expression, List <Expression> > generateAutoReqs = e => GenerateAutoReqs(e, parent); if (expr is LiteralExpr) { } else if (expr is ThisExpr) { } else if (expr is IdentifierExpr) { } else if (expr is SeqDisplayExpr) { SeqDisplayExpr e = (SeqDisplayExpr)expr; foreach (var elt in e.Elements) { reqs.AddRange(generateAutoReqs(elt)); } } else if (expr is FieldSelectExpr) { FieldSelectExpr e = (FieldSelectExpr)expr; reqs.AddRange(generateAutoReqs(e.Obj)); } else if (expr is SeqSelectExpr) { SeqSelectExpr e = (SeqSelectExpr)expr; reqs.AddRange(generateAutoReqs(e.Seq)); if (e.E0 != null) { reqs.AddRange(generateAutoReqs(e.E0)); } if (e.E1 != null) { reqs.AddRange(generateAutoReqs(e.E1)); } } else if (expr is SeqUpdateExpr) { SeqUpdateExpr e = (SeqUpdateExpr)expr; reqs.AddRange(generateAutoReqs(e.Seq)); reqs.AddRange(generateAutoReqs(e.Index)); reqs.AddRange(generateAutoReqs(e.Value)); } else if (expr is FunctionCallExpr) { FunctionCallExpr e = (FunctionCallExpr)expr; foreach (var arg in e.Args) { reqs.AddRange(generateAutoReqs(arg)); } if (parent == null || parent.Name != e.name) { ReqFunction(e.Function); reqs.AddRange(GatherReqs(e.Function, e.Args)); } } else if (expr is DatatypeValue) { DatatypeValue dtv = (DatatypeValue)expr; for (int i = 0; i < dtv.Arguments.Count; i++) { Expression arg = dtv.Arguments[i]; reqs.AddRange(generateAutoReqs(arg)); } } else if (expr is OldExpr) { } else if (expr is MatchExpr) { MatchExpr e = (MatchExpr)expr; reqs.AddRange(generateAutoReqs(e.Source)); List <MatchCaseExpr> newMatches = new List <MatchCaseExpr>(); foreach (MatchCaseExpr caseExpr in e.Cases) { MatchCaseExpr c = new MatchCaseExpr(caseExpr.name, caseExpr.Arguments, Andify(generateAutoReqs(caseExpr.Body))); newMatches.Add(c); } reqs.Add(new MatchExpr(e.Source, newMatches)); } else if (expr is FreshExpr) { } else if (expr is UnaryExpr) { UnaryExpr e = (UnaryExpr)expr; Expression arg = e.E; reqs.AddRange(generateAutoReqs(arg)); } else if (expr is BinaryExpr) { BinaryExpr e = (BinaryExpr)expr; switch (e.Op) { case BinaryExpr.Opcode.Imp: case BinaryExpr.Opcode.And: reqs.AddRange(generateAutoReqs(e.E0)); foreach (var req in generateAutoReqs(e.E1)) { reqs.Add(new BinaryExpr(Token.NoToken, BinaryExpr.Opcode.Imp, e.E0, req)); } break; case BinaryExpr.Opcode.Or: reqs.AddRange(generateAutoReqs(e.E0)); foreach (var req in generateAutoReqs(e.E1)) { reqs.Add(new BinaryExpr(Token.NoToken, BinaryExpr.Opcode.Imp, new UnaryExpr(Token.NoToken, UnaryExpr.Opcode.Not, e.E0), req)); } break; default: reqs.AddRange(generateAutoReqs(e.E0)); reqs.AddRange(generateAutoReqs(e.E1)); break; } } else if (expr is LetExpr) { var e = (LetExpr)expr; if (e.Exact) { foreach (var rhs in e.RHSs) { reqs.AddRange(generateAutoReqs(rhs)); } var new_reqs = generateAutoReqs(e.Body); if (new_reqs.Count > 0) { reqs.Add(new LetExpr(e.Exact, e.LHSs, e.RHSs, Andify(new_reqs))); } } } else if (expr is QuantifierExpr) { QuantifierExpr e = (QuantifierExpr)expr; var auto_reqs = generateAutoReqs(e.Term); if (auto_reqs.Count > 0) { Expression allReqsSatisfied = Andify(auto_reqs); Expression allReqsSatisfiedAndTerm = new BinaryExpr(Token.NoToken, BinaryExpr.Opcode.And, allReqsSatisfied, e.Term); e.Term = allReqsSatisfiedAndTerm; } } else if (expr is StmtExpr) { var e = (StmtExpr)expr; reqs.AddRange(generateAutoReqs(e.E)); } else if (expr is ITEExpr) { ITEExpr e = (ITEExpr)expr; reqs.AddRange(generateAutoReqs(e.Test)); reqs.Add(new ITEExpr(e.Test, Andify(generateAutoReqs(e.Thn)), Andify(generateAutoReqs(e.Els)))); } return(reqs); }
private TriggerAnnotation AnnotateQuantifier(QuantifierExpr expr) { return(AnnotateQuantifierOrLetExpr(expr, expr.BoundVars)); }
private Expr PrintQuantifierExpr(QuantifierExpr QE) { if (QE is ExistsExpr) { TW.Write("(exists"); } else if (QE is ForallExpr) { TW.Write("(forall"); } else { throw new NotSupportedException("Unsupported quantifier expr"); } PushIndent(); PrintSeperator(); TW.Write("("); PushIndent(); PrintSeperator(); foreach (var boundVar in QE.Dummies) { PrintSeperator(); TW.Write("(" + boundVar.Name + " " + GetSMTLIBType(boundVar.TypedIdent.Type) + ")"); } PopIndent(); PrintSeperator(); TW.Write(")"); PrintSeperator(); // Handle Triggers if (QE.Triggers == null || !PrintTriggers) { PrintExpr(QE.Body); } else { TW.Write("(!"); PushIndent(); PrintSeperator(); PrintExpr(QE.Body); PrintSeperator(); // fixme: pos! // Print triggers var trigger = QE.Triggers; if (trigger.Pos) { while (trigger != null) { // list of expressions TW.Write(":pattern ("); PushIndent(); PrintSeperator(); foreach (var triggerExpr in trigger.Tr) { PrintExpr(triggerExpr); PrintSeperator(); } PopIndent(); TW.Write(")"); trigger = trigger.Next; } } else { if (trigger.Tr.Count != 1) { throw new InvalidDataException("Negative trigger is malformed"); } // no-pattern takes an expression rather than a list of expressions TW.Write(":no-pattern"); PushIndent(); PrintSeperator(); PrintExpr(trigger.Tr[0]); PopIndent(); } PopIndent(); PrintSeperator(); TW.Write(")"); } PopIndent(); PrintSeperator(); TW.Write(")"); return(QE); }
internal QuantifierWithTriggers(QuantifierExpr quantifier) { this.quantifier = quantifier; this.RejectedCandidates = new List <TriggerCandidate>(); }
public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) { add(node); return(base.VisitQuantifierExpr(node)); }
public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) { FindInstantiationSources(node, "skolem_add_to_pool"); return(base.VisitQuantifierExpr(node)); }
public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) { return(base.VisitQuantifierExpr((QuantifierExpr)node.Clone())); }
public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) { node = base.VisitQuantifierExpr(node); quantifiersExist = true; return(node); }
public RtlExp GhostExpressionRec(Expression exp, bool inRecSpec = false, bool inRequiresOrOld = false) { Util.Assert(!isPrinting); exp = GetExp(exp); StmtExpr stmtExpr = exp as StmtExpr; IdentifierExpr idExp = exp as IdentifierExpr; LiteralExpr literal = exp as LiteralExpr; BinaryExpr binary = exp as BinaryExpr; UnaryExpr unary = exp as UnaryExpr; ITEExpr ite = exp as ITEExpr; ExistsExpr existsExp = exp as ExistsExpr; ForallExpr forallExp = exp as ForallExpr; LetExpr letExp = exp as LetExpr; MatchExpr matchExp = exp as MatchExpr; OldExpr oldExp = exp as OldExpr; FreshExpr freshExp = exp as FreshExpr; FunctionCallExpr funCall = exp as FunctionCallExpr; DatatypeValue dataVal = exp as DatatypeValue; FieldSelectExpr fieldSelect = exp as FieldSelectExpr; SeqSelectExpr seqSelect = exp as SeqSelectExpr; SeqUpdateExpr seqUpdate = exp as SeqUpdateExpr; SeqDisplayExpr seqDisplay = exp as SeqDisplayExpr; Func <Expression, RtlExp> G = e => GhostExpression(e, inRecSpec, inRequiresOrOld); if (stmtExpr != null) { if (stmtExprEnabled) { if (ignoreStmtExpr == 0) { AddGhostStatement(stmtExpr.S); } return(G(stmtExpr.E)); } else { throw new Exception("not implemented: cannot handle statement expression here"); } } else if (idExp != null) { return(AsVar(idExp)); } else if (literal != null && literal.Value is BigInteger) { return(new RtlInt((BigInteger)(literal.Value))); } else if (literal != null && literal.Value is bool) { return(new RtlLiteral((bool)(literal.Value) ? "true" : "false")); } else if (literal != null && literal.Value == null) { return(new RtlLiteral("ArrayOfInt(0 - 1, NO_ABS)")); } else if (literal != null && literal.Value is Microsoft.Basetypes.BigDec) { return(new RtlLiteral(((Microsoft.Basetypes.BigDec)literal.Value).ToDecimalString())); } else if (binary != null) { string op = null; string internalOp = null; CompileFunction compileFunction = this as CompileFunction; string thisFuncName = (compileFunction == null) ? null : compileFunction.function.Name; switch (binary.ResolvedOp) { case BinaryExpr.ResolvedOpcode.SeqEq: return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(binary.E0.Type), "Seq_Equal"), new RtlExp[] { G(binary.E0), G(binary.E1) })); case BinaryExpr.ResolvedOpcode.SeqNeq: return(new RtlLiteral("(!" + new RtlApply(dafnySpec.GetSeqOperationName(AppType(binary.E0.Type), "Seq_Equal"), new RtlExp[] { G(binary.E0), G(binary.E1) }) + ")")); case BinaryExpr.ResolvedOpcode.Concat: return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(binary.Type), "Seq_Append"), new RtlExp[] { G(binary.E0), G(binary.E1) })); } if (binary.Op == BinaryExpr.Opcode.Exp) { binary = new BinaryExpr(binary.tok, BinaryExpr.Opcode.Imp, binary.E0, binary.E1); } switch (binary.Op) { case BinaryExpr.Opcode.Disjoint: case BinaryExpr.Opcode.In: case BinaryExpr.Opcode.NotIn: throw new Exception("not implemented: binary operator '" + BinaryExpr.OpcodeString(binary.Op) + "'"); } if (AppType(binary.E0.Type) is IntType && AppType(binary.E1.Type) is IntType) { switch (binary.Op) { case BinaryExpr.Opcode.Le: internalOp = "INTERNAL_le_boogie"; break; case BinaryExpr.Opcode.Lt: internalOp = "INTERNAL_lt_boogie"; break; case BinaryExpr.Opcode.Ge: internalOp = "INTERNAL_ge_boogie"; break; case BinaryExpr.Opcode.Gt: internalOp = "INTERNAL_gt_boogie"; break; case BinaryExpr.Opcode.Add: internalOp = "INTERNAL_add_boogie"; break; case BinaryExpr.Opcode.Sub: internalOp = "INTERNAL_sub_boogie"; break; case BinaryExpr.Opcode.Mul: op = "*"; if (thisFuncName != "INTERNAL_mul") { internalOp = FunName("INTERNAL__mul"); } break; case BinaryExpr.Opcode.Div: op = "div"; if (thisFuncName != "INTERNAL_div") { internalOp = FunName("INTERNAL__div"); } break; case BinaryExpr.Opcode.Mod: op = "mod"; if (thisFuncName != "INTERNAL_mod") { internalOp = FunName("INTERNAL__mod"); } break; default: op = BinaryExpr.OpcodeString(binary.Op); break; } } else { op = BinaryExpr.OpcodeString(binary.Op); } if (internalOp == null) { return(new RtlBinary(op, G(binary.E0), G(binary.E1))); } else { return(new RtlApply(internalOp, new RtlExp[] { G(binary.E0), G(binary.E1) })); } } else if (unary != null && unary.Op == UnaryExpr.Opcode.Not) { return(new RtlLiteral("(!(" + G(unary.E) + "))")); } else if (unary != null && unary.Op == UnaryExpr.Opcode.SeqLength) { return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(unary.E.Type), "Seq_Length"), new RtlExp[] { G(unary.E) })); } else if (ite != null) { return(GhostIfThenElse(G(ite.Test), () => G(ite.Thn), () => G(ite.Els))); } else if (funCall != null) { switch (funCall.Function.Name) { case "left": case "right": case "relation": case "public": Util.Assert(funCall.Args.Count == 1); return(new RtlApply(funCall.Function.Name, new RtlExp[] { G(funCall.Args[0]) })); case "sizeof": Util.Assert(funCall.Args.Count == 1); return(new RtlApply(funCall.Function.Name + "##" + TypeString(AppType(funCall.Args[0].Type)), new RtlExp[] { G(funCall.Args[0]) })); case "INTERNAL_add_raw": Util.Assert(funCall.Args.Count == 2); return(new RtlBinary("+", G(funCall.Args[0]), G(funCall.Args[1]))); case "INTERNAL_sub_raw": Util.Assert(funCall.Args.Count == 2); return(new RtlBinary("-", G(funCall.Args[0]), G(funCall.Args[1]))); case "IntToReal": Util.Assert(funCall.Args.Count == 1); return(new RtlApply("real", new RtlExp[] { G(funCall.Args[0]) })); case "RealToInt": Util.Assert(funCall.Args.Count == 1); return(new RtlApply("int", new RtlExp[] { G(funCall.Args[0]) })); } TypeApply app = dafnySpec.Compile_Function(funCall.Function, funCall.TypeArgumentSubstitutions.ToDictionary(p => p.Key, p => AppType(p.Value))); string name = FunName(SimpleName(app.AppName())); string fullName = FunName(SimpleName(app.AppFullName())); List <RtlExp> rtlArgs = funCall.Args.Select(G).ToList(); List <RtlExp> rtlReads = funCall.Function.Reads.Where(e => e.Field != null).ToList() .ConvertAll(e => (RtlExp) new RtlVar( GhostVar(e.FieldName), e.Field.IsGhost, AppType(e.Field.Type))); rtlArgs = rtlReads.Concat(rtlArgs).ToList(); if (name.EndsWith("__INTERNAL__HEAP")) { name = name.Substring(0, name.Length - "__INTERNAL__HEAP".Length); } else if (DafnySpec.IsHeapFunction(funCall.Function)) { rtlArgs.Insert(0, new RtlLiteral(inRequiresOrOld ? "$absMem_old" : "$absMem")); } if (Attributes.Contains(funCall.Function.Attributes, "opaque") && funCall.Function.Formals.Count + rtlReads.Count == 0) { rtlArgs.Insert(0, new RtlLiteral("true")); } if (fullName == recFunName) { name = fullName; } if (name == recFunName) { recCalls.Add(new List <RtlExp>(rtlArgs)); rtlArgs.Insert(0, new RtlApply("decreases_" + name, new List <RtlExp>(rtlArgs))); rtlArgs.Insert(1, new RtlLiteral(inRecSpec ? "__unroll" : "__unroll + 1")); name = "rec_" + name; } return(new RtlApply(name, rtlArgs)); } else if (dataVal != null) { bool isSeq = dataVal.Type.TypeName(null).StartsWith("Seq<"); return(new RtlApply((isSeq ? "_" : "") + dafnySpec.Compile_Constructor( dataVal.Type, dataVal.Ctor.Name, dataVal.InferredTypeArgs, typeApply.typeArgs).AppName(), dataVal.Arguments.Select(G))); } else if (existsExp != null || forallExp != null) { QuantifierExpr qExp = (QuantifierExpr)exp; bool isForall = forallExp != null; var varTuples = qExp.BoundVars.Select(v => Tuple.Create(GhostVar(v.Name), v.IsGhost, v.Type)); var oldRenamer = PushRename(qExp.BoundVars.Select(v => v.Name)); var oldStmtExprEnabled = stmtExprEnabled; stmtExprEnabled = false; RtlExp rExp = new RtlLiteral((isForall ? "(forall " : "(exists ") + string.Join(", ", qExp.BoundVars.Select(v => GhostVar(v.Name) + ":" + TypeString(AppType(v.Type)))) + " :: " + Triggers(qExp.Attributes, G) + " " + GetTypeWellFormedExp(varTuples.ToList(), isForall ? "==>" : "&&", G(qExp.Term)) + ")"); stmtExprEnabled = oldStmtExprEnabled; PopRename(oldRenamer); return(rExp); } else if (letExp != null) { List <RtlExp> rhss; if (letExp.Exact) { rhss = letExp.RHSs.ConvertAll(e => G(e)); } else if (letExp.LHSs.Count == 1 && LiteralExpr.IsTrue(letExp.RHSs[0]) && AppType(letExp.LHSs[0].Var.Type) is IntType) { rhss = new List <RtlExp> { new RtlLiteral("0") }; } else { throw new Exception("not implemented: LetExpr: " + letExp); } return(GhostLet(exp.tok, letExp.LHSs.ConvertAll(lhs => lhs.Var), rhss, () => G(letExp.Body))); } else if (matchExp != null) { if (matchExp.MissingCases.Count != 0) { throw new Exception("not implemented: MatchExpr with missing cases: " + matchExp); } //- match src case c1(ps1) => e1 ... cn(psn) => en //- --> //- let x := src in //- if x is c1 then let ps1 := ...x.f1... in e1 else //- if x is c2 then let ps2 := ...x.f2... in e2 else //- let ps3 := ...x.f3... in e3 var src = G(matchExp.Source); var cases = matchExp.Cases; string x = TempName(); Func <RtlExp> body = null; for (int i = cases.Count; i > 0;) { i--; MatchCaseExpr c = cases[i]; Func <List <RtlExp> > cRhss = () => c.Ctor.Formals.ConvertAll(f => (RtlExp) new RtlLiteral("(" + f.Name + "#" + c.Ctor.Name + "(" + GhostVar(x) + "))")); Func <RtlExp> ec = () => GhostLet(exp.tok, c.Arguments, cRhss(), () => G(c.Body)); if (body == null) { body = ec; } else { var prevBody = body; body = () => GhostIfThenElse(new RtlLiteral("(" + GhostVar(x) + " is " + c.Ctor.Name + ")"), ec, prevBody); } } return(GhostLet(exp.tok, new List <BoundVar> { new BoundVar(exp.tok, x, matchExp.Source.Type) }, new List <RtlExp> { src }, body)); } else if (oldExp != null) { return(new RtlLiteral("old(" + GhostExpression(oldExp.E, inRecSpec, true) + ")")); } else if (freshExp != null) { Util.Assert(DafnySpec.IsArrayType(freshExp.E.Type)); string abs = G(freshExp.E) + ".arrAbs"; return(new RtlLiteral("(heap_old.absData[" + abs + "] is AbsNone)")); } else if (fieldSelect != null && fieldSelect.FieldName.EndsWith("?")) { string constructor = fieldSelect.FieldName.Substring(0, fieldSelect.FieldName.Length - 1); constructor = dafnySpec.Compile_Constructor(fieldSelect.Obj.Type, constructor, null, typeApply.typeArgs).AppName(); bool isSeq = fieldSelect.Obj.Type.TypeName(null).StartsWith("Seq<"); return(isSeq ? new RtlLiteral("is_" + constructor + "(" + G(fieldSelect.Obj) + ")") : new RtlLiteral("((" + G(fieldSelect.Obj) + ") is " + constructor + ")")); } else if (fieldSelect != null && !fieldSelect.Field.IsStatic && AppType(fieldSelect.Obj.Type) is UserDefinedType && fieldSelect.Field is DatatypeDestructor) { DatatypeDestructor field = (DatatypeDestructor)fieldSelect.Field; string constructor = dafnySpec.Compile_Constructor(fieldSelect.Obj.Type, field.EnclosingCtor.Name, null, typeApply.typeArgs).AppName(); bool isSeq = fieldSelect.Obj.Type.TypeName(null).StartsWith("Seq<"); return(new RtlLiteral("(" + fieldSelect.FieldName + (isSeq ? "_" : "#") + constructor + "(" + G(fieldSelect.Obj) + "))")); } else if (fieldSelect != null && DafnySpec.IsArrayType(AppType(fieldSelect.Obj.Type)) && fieldSelect.FieldName == "Length") { return(new RtlLiteral("(Arr_Length(" + G(fieldSelect.Obj) + "))")); } else if (fieldSelect != null && fieldSelect.Obj is ImplicitThisExpr) { //- we don't support objects yet, so interpret this as a global variable return(new RtlVar(GhostVar(fieldSelect.FieldName), true, fieldSelect.Type)); } else if (seqSelect != null) { if (seqSelect.SelectOne && DafnySpec.IsArrayType(AppType(seqSelect.Seq.Type))) { return(new RtlExpComputed(e => "fun_INTERNAL__array__elems__index(" + (inRequiresOrOld ? "$absMem_old" : "$absMem") + "[" + e.args[0] + ".arrAbs], (" + e.args[1] + "))", new RtlExp[] { G(seqSelect.Seq), G(seqSelect.E0) })); } else if (seqSelect.SelectOne) { return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqSelect.Seq.Type), "Seq_Index"), new RtlExp[] { G(seqSelect.Seq), G(seqSelect.E0) })); } else { RtlExp seq = G(seqSelect.Seq); if (DafnySpec.IsArrayType(AppType(seqSelect.Seq.Type))) { seq = new RtlApply(FunName("Seq__FromArray"), new RtlExp[] { new RtlLiteral(inRequiresOrOld ? "$absMem_old" : "$absMem"), seq }); } if (seqSelect.E1 != null) { seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqSelect.Type), "Seq_Take"), new RtlExp[] { seq, G(seqSelect.E1) }); } if (seqSelect.E0 != null) { seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqSelect.Type), "Seq_Drop"), new RtlExp[] { seq, G(seqSelect.E0) }); } return(seq); } } else if (seqUpdate != null) { if (seqUpdate.ResolvedUpdateExpr != null) { return(GhostExpressionRec(seqUpdate.ResolvedUpdateExpr, inRecSpec, inRequiresOrOld)); } return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqUpdate.Seq.Type), "Seq_Update"), new RtlExp[] { G(seqUpdate.Seq), G(seqUpdate.Index), G(seqUpdate.Value) })); } else if (seqDisplay != null) { RtlExp seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqDisplay.Type), "Seq_Empty"), new RtlExp[0]); foreach (Expression ei in seqDisplay.Elements) { seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqDisplay.Type), "Seq_Build"), new RtlExp[] { seq, G(ei) }); } return(seq); } else { throw new Exception("not implemented: " + exp); } }
internal static bool NeedsAutoTriggers(QuantifierExpr quantifier) { Contract.Requires(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 Expression TreeToExpression() { Contract.Ensures(Contract.Result <Expression>() != null); if (IsLeaf()) { return(Data); } if (Data is TacnyBinaryExpr) { TacnyBinaryExpr bexp = (TacnyBinaryExpr)Data; Expression E0 = LChild.TreeToExpression(); Expression E1 = RChild?.TreeToExpression(); return(new TacnyBinaryExpr(bexp.tok, bexp.Op, E0, E1)); } if (Data is BinaryExpr) { BinaryExpr bexp = (BinaryExpr)Data; Expression E0 = LChild.TreeToExpression(); Expression E1 = RChild?.TreeToExpression(); return(new BinaryExpr(bexp.tok, bexp.Op, E0, E1)); } if (Data is ChainingExpression) { List <Expression> operands = null; ChainingExpression ce = (ChainingExpression)Data; operands = GetLeafData(); operands.RemoveAt(1); // hack to remove the duplicate name statement List <BinaryExpr.Opcode> operators = new List <BinaryExpr.Opcode>(); BinaryExpr expr = (BinaryExpr)LChild.TreeToExpression(); operators.Add(((BinaryExpr)expr.E0).Op); operators.Add(((BinaryExpr)expr.E1).Op); return(new ChainingExpression(ce.tok, operands, operators, ce.PrefixLimits, expr)); } if (Data is ParensExpression) { return(new ParensExpression(Data.tok, LChild.TreeToExpression())); } if (Data is QuantifierExpr) { QuantifierExpr qexp = (QuantifierExpr)Data; if (Data is ForallExpr) { return(new ForallExpr(qexp.tok, qexp.BoundVars, qexp.Range, LChild.TreeToExpression(), qexp.Attributes)); } if (Data is ExistsExpr) { return(new ExistsExpr(qexp.tok, qexp.BoundVars, qexp.Range, LChild.TreeToExpression(), qexp.Attributes)); } } else if (Data is NegationExpression) { return(new NegationExpression(Data.tok, LChild.TreeToExpression())); } else if (Data is SeqSelectExpr) { var e = (SeqSelectExpr)Data; return(new SeqSelectExpr(e.tok, e.SelectOne, e.Seq, LChild.TreeToExpression(), RChild?.TreeToExpression())); } return(Data); }
internal static bool AllowsMatchingLoops(QuantifierExpr quantifier) { Contract.Requires(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")); }