public void SimpleForAllWithTrigger() { var builder = GetSimpleBuilder(); var freeVarX = GetVariable("x", BasicType.Int); var xid = new IdentifierExpr(Token.NoToken, freeVarX); var fb = new FunctionCallBuilder(); var funcCall = fb.CreateUninterpretedFunctionCall("f", BPLType.Int, new List <BPLType>() { BPLType.Int }); var body = builder.Gt(builder.UFC(funcCall, xid), xid); // Single trigger var triggers = new Microsoft.Boogie.Trigger(Token.NoToken, /*positive=*/ true, new List <Expr>() { builder.UFC(funcCall, xid) }, null); var result = builder.ForAll(new List <Variable>() { freeVarX }, body, triggers); Assert.AreEqual("(forall x: int :: { f(x) } f(x) > x)", result.ToString()); CheckIsBoolType(result); }
// Note: if the trigger is null, makes a forall without any triggers static Bpl.Expr BplForall(IEnumerable <Bpl.Variable> args_in, Bpl.Trigger trg, Bpl.Expr body) { if (trg == null) { return(BplForall(args_in, body)); // NO_TRIGGER } else { var args = new List <Bpl.Variable>(args_in); if (args.Count == 0) { return(body); } else { return(new Bpl.ForallExpr(body.tok, args, trg, body)); } } }
public ExistsExpr(IToken tok, List<Variable> dummies, Trigger triggers, Expr body, bool immutable=false) : base(tok, new List<TypeVariable>(), dummies, null, triggers, body, immutable) { Contract.Requires(body != null); Contract.Requires(dummies != null); Contract.Requires(tok != null); Contract.Requires(dummies.Count > 0); }
public ExistsExpr(IToken/*!*/ tok, List<TypeVariable>/*!*/ typeParams, List<Variable>/*!*/ dummies, QKeyValue kv, Trigger triggers, Expr/*!*/ body, bool immutable=false) : base(tok, typeParams, dummies, kv, triggers, body, immutable) { Contract.Requires(tok != null); Contract.Requires(typeParams != null); Contract.Requires(dummies != null); Contract.Requires(body != null); Contract.Requires(dummies.Count + typeParams.Count > 0); }
public void AddLast(Trigger other) { Trigger current = this; while (current.Next != null) { current = current.Next; } current.Next = other; }
public ForallExpr(IToken tok, List<Variable> dummies, Trigger triggers, Expr body) : base(tok, new List<TypeVariable>(), dummies, null, triggers, body) { Contract.Requires(body != null); Contract.Requires(dummies != null); Contract.Requires(tok != null); Contract.Requires(dummies.Count > 0); }
public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) { currentTrigger = node.Triggers; while (currentTrigger != null) { foreach (var e in currentTrigger.Tr) { VisitExpr(e); } currentTrigger = currentTrigger.Next; } return base.VisitQuantifierExpr(node); }
public override Trigger VisitTrigger(Trigger node) { Contract.Ensures(Contract.Result<Trigger>() == node); Trigger origNext = node.Next; if (origNext != null) { this.VisitTrigger(origNext); } this.VisitExprSeq(node.Tr.ToList()); return node; }
void QuantifierBody(IToken/*!*/ q, out List<TypeVariable>/*!*/ typeParams, out List<Variable>/*!*/ ds, out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { Contract.Requires(q != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); Contract.Ensures(Contract.ValueAtReturn(out ds) != null); Contract.Ensures(Contract.ValueAtReturn(out body) != null); trig = null; typeParams = new List<TypeVariable> (); IToken/*!*/ tok; kv = null; ds = new List<Variable> (); if (la.kind == 20) { TypeParams(out tok, out typeParams); if (la.kind == 1 || la.kind == 28) { BoundVars(q, out ds); } } else if (la.kind == 1 || la.kind == 28) { BoundVars(q, out ds); } else SynErr(129); QSep(); while (la.kind == 28) { AttributeOrTrigger(ref kv, ref trig); } Expression(out body); }
static Bpl.Expr BplForall(Bpl.Variable arg, Bpl.Trigger trg, Bpl.Expr body) { return(BplForall(Singleton(arg), trg, body)); }
public override Expr VisitLambdaExpr(LambdaExpr lambda) { var baseResult = base.VisitLambdaExpr(lambda); lambda = baseResult as LambdaExpr; if (lambda == null) { return baseResult; // apparently, the base visitor already turned the lambda into something else } // We start by getting rid of any use of "old" inside the lambda. This is done as follows. // For each variable "g" occurring inside lambda as "old(... g ...)", create a new name "og". // Replace each old occurrence of "g" with "og", removing the enclosing "old" wrappers. var oldFinder = new OldFinder(); oldFinder.Visit(lambda); var oldSubst = new Dictionary<Variable, Expr>(); // g -> g0 var callOldMapping = new Dictionary<Variable, Expr>(); // g0 -> old(g) foreach (var v in oldFinder.FreeOldVars) { var g = v as GlobalVariable; if (g != null) { var g0 = new GlobalVariable(g.tok, new TypedIdent(g.tok, g.TypedIdent.Name + "@old", g.TypedIdent.Type)); oldSubst.Add(g, new IdentifierExpr(g0.tok, g0)); callOldMapping.Add(g0, new OldExpr(g0.tok, new IdentifierExpr(g.tok, g))); } } var lambdaBody = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromHashtable(new Dictionary<Variable,Expr>()), Substituter.SubstitutionFromHashtable(oldSubst), lambda.Body); var lambdaAttrs = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromHashtable(new Dictionary<Variable, Expr>()), Substituter.SubstitutionFromHashtable(oldSubst), lambda.Attributes); if (0 < CommandLineOptions.Clo.VerifySnapshots && QKeyValue.FindStringAttribute(lambdaAttrs, "checksum") == null) { // Attach a dummy checksum to avoid issues in the dependency analysis. var checksumAttr = new QKeyValue(lambda.tok, "checksum", new List<object> { "lambda expression" }, null); if (lambdaAttrs == null) { lambdaAttrs = checksumAttr; } else { lambdaAttrs.AddLast(checksumAttr); } } // this is ugly, the output will depend on hashing order var subst = new Dictionary<Variable, Expr>(); var substFnAttrs = new Dictionary<Variable, Expr>(); var formals = new List<Variable>(); var callArgs = new List<Expr>(); var axCallArgs = new List<Expr>(); var dummies = new List<Variable>(lambda.Dummies); var freeTypeVars = new List<TypeVariable>(); var fnTypeVarActuals = new List<Type/*!*/>(); var freshTypeVars = new List<TypeVariable>(); // these are only used in the lambda@n function's definition // compute the free variables of the lambda expression, but with lambdaBody instead of lambda.Body Set freeVars = new Set(); BinderExpr.ComputeBinderFreeVariables(lambda.TypeParameters, lambda.Dummies, lambdaBody, lambdaAttrs, freeVars); foreach (object o in freeVars) { // 'o' is either a Variable or a TypeVariable. if (o is Variable) { var v = o as Variable; var ti = new TypedIdent(v.TypedIdent.tok, v.TypedIdent.Name, v.TypedIdent.Type); var f = new Formal(v.tok, ti, true); formals.Add(f); substFnAttrs.Add(v, new IdentifierExpr(f.tok, f)); var b = new BoundVariable(v.tok, ti); dummies.Add(b); if (callOldMapping.ContainsKey(v)) { callArgs.Add(callOldMapping[v]); } else { callArgs.Add(new IdentifierExpr(v.tok, v)); } Expr id = new IdentifierExpr(b.tok, b); subst.Add(v, id); axCallArgs.Add(id); } else { var tv = (TypeVariable)o; freeTypeVars.Add(tv); fnTypeVarActuals.Add(tv); freshTypeVars.Add(new TypeVariable(tv.tok, tv.Name)); } } var sw = new System.IO.StringWriter(); var wr = new TokenTextWriter(sw, true); lambda.Emit(wr); string lam_str = sw.ToString(); FunctionCall fcall; IToken tok = lambda.tok; Formal res = new Formal(tok, new TypedIdent(tok, TypedIdent.NoName, cce.NonNull(lambda.Type)), false); if (liftedLambdas.TryGetValue(lambda, out fcall)) { if (CommandLineOptions.Clo.TraceVerify) { Console.WriteLine("Old lambda: {0}", lam_str); } } else { if (CommandLineOptions.Clo.TraceVerify) { Console.WriteLine("New lambda: {0}", lam_str); } Function fn = new Function(tok, FreshLambdaFunctionName(), freshTypeVars, formals, res, "auto-generated lambda function", Substituter.Apply(Substituter.SubstitutionFromHashtable(substFnAttrs), lambdaAttrs)); fn.OriginalLambdaExprAsString = lam_str; fcall = new FunctionCall(new IdentifierExpr(tok, fn.Name)); fcall.Func = fn; // resolve here liftedLambdas[lambda] = fcall; List<Expr/*!*/> selectArgs = new List<Expr/*!*/>(); foreach (Variable/*!*/ v in lambda.Dummies) { Contract.Assert(v != null); selectArgs.Add(new IdentifierExpr(v.tok, v)); } NAryExpr axcall = new NAryExpr(tok, fcall, axCallArgs); axcall.Type = res.TypedIdent.Type; axcall.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); NAryExpr select = Expr.Select(axcall, selectArgs); select.Type = lambdaBody.Type; List<Type/*!*/> selectTypeParamActuals = new List<Type/*!*/>(); List<TypeVariable> forallTypeVariables = new List<TypeVariable>(); foreach (TypeVariable/*!*/ tp in lambda.TypeParameters) { Contract.Assert(tp != null); selectTypeParamActuals.Add(tp); forallTypeVariables.Add(tp); } forallTypeVariables.AddRange(freeTypeVars); select.TypeParameters = SimpleTypeParamInstantiation.From(lambda.TypeParameters, selectTypeParamActuals); Expr bb = Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambdaBody); NAryExpr body = Expr.Eq(select, bb); body.Type = Type.Bool; body.TypeParameters = SimpleTypeParamInstantiation.EMPTY; Trigger trig = new Trigger(select.tok, true, new List<Expr> { select }); lambdaFunctions.Add(fn); lambdaAxioms.Add(new ForallExpr(tok, forallTypeVariables, dummies, Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambdaAttrs), trig, body)); } NAryExpr call = new NAryExpr(tok, fcall, callArgs); call.Type = res.TypedIdent.Type; call.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); return call; }
public override Absy Visit(Absy node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result<Absy>() != null); node = base.Visit(node); LambdaExpr lambda = node as LambdaExpr; if (lambda != null) { IToken/*!*/ tok = lambda.tok; Contract.Assert(tok != null); Set freeVars = new Set(); lambda.ComputeFreeVariables(freeVars); // this is ugly, the output will depend on hashing order Dictionary<Variable, Expr> subst = new Dictionary<Variable, Expr>(); List<Variable> formals = new List<Variable>(); List<Expr> callArgs = new List<Expr>(); List<Expr> axCallArgs = new List<Expr>(); List<Variable> dummies = new List<Variable>(lambda.Dummies); List<TypeVariable> freeTypeVars = new List<TypeVariable>(); List<Type/*!*/> fnTypeVarActuals = new List<Type/*!*/>(); List<TypeVariable> freshTypeVars = new List<TypeVariable>(); // these are only used in the lambda@n function's definition foreach (object o in freeVars) { // 'o' is either a Variable or a TypeVariable. Since the lambda desugaring happens only // at the outermost level of a program (where there are no mutable variables) and, for // procedure bodies, after the statements have been passified (when mutable variables have // been replaced by immutable incarnations), we are interested only in BoundVar's and // TypeVariable's. BoundVariable v = o as BoundVariable; if (v != null) { TypedIdent ti = new TypedIdent(v.TypedIdent.tok, v.TypedIdent.Name, v.TypedIdent.Type); Formal f = new Formal(v.tok, ti, true); formals.Add(f); BoundVariable b = new BoundVariable(v.tok, ti); dummies.Add(b); callArgs.Add(new IdentifierExpr(v.tok, v)); Expr/*!*/ id = new IdentifierExpr(f.tok, b); Contract.Assert(id != null); subst.Add(v, id); axCallArgs.Add(id); } else if (o is TypeVariable) { TypeVariable tv = (TypeVariable)o; freeTypeVars.Add(tv); fnTypeVarActuals.Add(tv); freshTypeVars.Add(new TypeVariable(tv.tok, tv.Name)); } } Formal res = new Formal(tok, new TypedIdent(tok, TypedIdent.NoName, cce.NonNull(lambda.Type)), false); Function fn = new Function(tok, "lambda@" + lambdaid++, freshTypeVars, formals, res, "auto-generated lambda function", lambda.Attributes); lambdaFunctions.Add(fn); FunctionCall fcall = new FunctionCall(new IdentifierExpr(tok, fn.Name)); fcall.Func = fn; // resolve here List<Expr/*!*/> selectArgs = new List<Expr/*!*/>(); foreach (Variable/*!*/ v in lambda.Dummies) { Contract.Assert(v != null); selectArgs.Add(new IdentifierExpr(v.tok, v)); } NAryExpr axcall = new NAryExpr(tok, fcall, axCallArgs); axcall.Type = res.TypedIdent.Type; axcall.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); NAryExpr select = Expr.Select(axcall, selectArgs); select.Type = lambda.Body.Type; List<Type/*!*/> selectTypeParamActuals = new List<Type/*!*/>(); List<TypeVariable> forallTypeVariables = new List<TypeVariable>(); foreach (TypeVariable/*!*/ tp in lambda.TypeParameters) { Contract.Assert(tp != null); selectTypeParamActuals.Add(tp); forallTypeVariables.Add(tp); } forallTypeVariables.AddRange(freeTypeVars); select.TypeParameters = SimpleTypeParamInstantiation.From(lambda.TypeParameters, selectTypeParamActuals); Expr bb = Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambda.Body); NAryExpr body = Expr.Eq(select, bb); body.Type = Type.Bool; body.TypeParameters = SimpleTypeParamInstantiation.EMPTY; Trigger trig = new Trigger(select.tok, true, new List<Expr> { select }); lambdaAxioms.Add(new ForallExpr(tok, forallTypeVariables, dummies, lambda.Attributes, trig, body)); NAryExpr call = new NAryExpr(tok, fcall, callArgs); call.Type = res.TypedIdent.Type; call.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); return call; } return node; }
public static void ComputeBinderFreeVariables(List <TypeVariable> typeParameters, List <Variable> dummies, Expr body, Trigger triggers, QKeyValue attributes, Set freeVars) { Contract.Requires(dummies != null); Contract.Requires(body != null); foreach (var v in dummies) { Contract.Assert(v != null); Contract.Assert(!freeVars[v]); } body.ComputeFreeVariables(freeVars); for (var trig = triggers; trig != null; trig = trig.Next) { foreach (var e in trig.Tr) { e.ComputeFreeVariables(freeVars); } } for (var a = attributes; a != null; a = a.Next) { foreach (var o in a.Params) { var e = o as Expr; if (e != null) { e.ComputeFreeVariables(freeVars); } } } foreach (var v in dummies) { freeVars.AddRange(v.TypedIdent.Type.FreeVariables); } freeVars.RemoveRange(dummies); freeVars.RemoveRange(typeParameters); }
public Trigger(IToken/*!*/ tok, bool pos, List<Expr>/*!*/ tr, Trigger next) : base(tok) { Contract.Requires(tok != null); Contract.Requires(tr != null); Contract.Requires(1 <= tr.Count); Contract.Requires(pos || tr.Count == 1); this.Pos = pos; this.Tr = tr; this.Next = next; }
public QuantifierExpr(IToken/*!*/ tok, List<TypeVariable>/*!*/ typeParameters, List<Variable>/*!*/ dummies, QKeyValue kv, Trigger triggers, Expr/*!*/ body, bool immutable) : base(tok, typeParameters, dummies, kv, body, immutable) { Contract.Requires(tok != null); Contract.Requires(typeParameters != null); Contract.Requires(dummies != null); Contract.Requires(body != null); Contract.Requires(dummies.Count + typeParameters.Count > 0); Contract.Assert((this is ForallExpr) || (this is ExistsExpr)); Triggers = triggers; SkolemId = GetNextSkolemId(); }
// if the user says ( forall x :: forall y :: ... ) and specifies *no* triggers, we transform it to // (forall x, y :: ... ) which may help the prover to pick trigger terms // // (Note: there used to be a different criterion here, which allowed merging when triggers were specified, which could cause prover errors due to resulting unbound variables in the triggers) private void MergeAdjecentQuantifier() { QuantifierExpr qbody = Body as QuantifierExpr; if (!(qbody != null && (qbody is ForallExpr) == (this is ForallExpr) && Triggers == null)) { return; } qbody.MergeAdjecentQuantifier(); if (this.Triggers != null || qbody.Triggers != null) { return; } Body = qbody.Body; TypeParameters.AddRange(qbody.TypeParameters); Dummies.AddRange(qbody.Dummies); Triggers = qbody.Triggers; if (qbody.Attributes != null) { if (Attributes == null) { Attributes = qbody.Attributes; } else { QKeyValue p = Attributes; while (p.Next != null) { p = p.Next; } p.Next = qbody.Attributes; } } }
static Bpl.Expr BplForall(Bpl.IToken tok, List <Bpl.TypeVariable> typeParams, List <Bpl.Variable> formals, Bpl.QKeyValue kv, Bpl.Trigger triggers, Bpl.Expr body, bool immutable = false) { return((typeParams.Count == 0 && formals.Count == 0) ? body : new Bpl.ForallExpr(tok, typeParams, formals, kv, triggers, body, immutable)); }
void AttributeOrTrigger(ref QKeyValue kv, ref Trigger trig) { IToken/*!*/ tok; Expr/*!*/ e; List<Expr>/*!*/ es; string key; List<object/*!*/> parameters; object/*!*/ param; Expect(28); tok = t; if (la.kind == 12) { Get(); Expect(1); key = t.val; parameters = new List<object/*!*/>(); if (StartOf(16)) { AttributeParameter(out param); parameters.Add(param); while (la.kind == 13) { Get(); AttributeParameter(out param); parameters.Add(param); } } if (key == "nopats") { if (parameters.Count == 1 && parameters[0] is Expr) { e = (Expr)parameters[0]; if(trig==null){ trig = new Trigger(tok, false, new List<Expr> { e }, null); } else { trig.AddLast(new Trigger(tok, false, new List<Expr> { e }, null)); } } else { this.SemErr("the 'nopats' quantifier attribute expects a string-literal parameter"); } } else { if (kv==null) { kv = new QKeyValue(tok, key, parameters, null); } else { kv.AddLast(new QKeyValue(tok, key, parameters, null)); } } } else if (StartOf(9)) { Expression(out e); es = new List<Expr> { e }; while (la.kind == 13) { Get(); Expression(out e); es.Add(e); } if (trig==null) { trig = new Trigger(tok, true, es, null); } else { trig.AddLast(new Trigger(tok, true, es, null)); } } else SynErr(133); Expect(29); }
public virtual Trigger VisitTrigger(Trigger node) { Contract.Requires(node != null); Contract.Ensures(Contract.Result<Trigger>() != null); Trigger origNext = node.Next; if (origNext != null) { Trigger newNext = this.VisitTrigger(origNext); if (newNext != origNext) { node = new Trigger(node.tok, node.Pos, node.Tr); // note: this creates sharing between the old and new Tr sequence node.Next = newNext; } } node.Tr = this.VisitExprSeq(node.Tr); return node; }
public virtual Trigger VisitTrigger(Trigger node) { Contract.Requires(node != null); Contract.Ensures(Contract.Result<Trigger>() != null); Trigger origNext = node.Next; if (origNext != null) { Trigger newNext = this.VisitTrigger(origNext); if (newNext != origNext) { node = new Trigger(node.tok, node.Pos, node.Tr.ToList()); node.Next = newNext; } } node.Tr = this.VisitExprSeq(node.Tr.ToList()); return node; }
public Trigger(IToken/*!*/ tok, bool pos, IEnumerable<Expr>/*!*/ tr, Trigger next = null) : base(tok) { Contract.Requires(tok != null); Contract.Requires(tr != null); Contract.Requires(tr.Count() >= 1); Contract.Requires(pos || tr.Count() == 1); this.Pos = pos; this.Tr = new List<Expr>(tr); this.Next = next; }
public override Trigger VisitTrigger(Trigger node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result<Trigger>() != null); return base.VisitTrigger((Trigger)node.Clone()); }
public override Trigger VisitTrigger(Trigger node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result <Trigger>() != null); return(base.VisitTrigger((Trigger)node.Clone())); }