//----------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- using Microsoft.Boogie; using AI = Microsoft.AbstractInterpretationFramework; using Microsoft.Contracts; using Microsoft.Basetypes; namespace Microsoft.Boogie.AbstractInterpretation { public class BoogiePropFactory : BoogieFactory, AI.IQuantPropExprFactory { public AI.IFunApp! False { get { return Expr.False; } } public AI.IFunApp! True { get { return Expr.True; } } public AI.IFunApp! Not(AI.IExpr! p) { return Expr.Unary(Token.NoToken, UnaryOperator.Opcode.Not, IExpr2Expr(p)); } public AI.IFunApp! And(AI.IExpr! p, AI.IExpr! q) { return Expr.Binary(BinaryOperator.Opcode.And, IExpr2Expr(p), IExpr2Expr(q)); } public AI.IFunApp! Or(AI.IExpr! p, AI.IExpr! q) { return Expr.Binary(BinaryOperator.Opcode.Or, IExpr2Expr(p), IExpr2Expr(q)); } public AI.IFunApp! Implies(AI.IExpr! p, AI.IExpr! q) { return Expr.Binary(BinaryOperator.Opcode.Imp, IExpr2Expr(p), IExpr2Expr(q)); } public AI.IFunApp! Exists(AI.IFunction! p) { return (AI.IFunApp)(new ExistsExpr(Token.NoToken, new VariableSeq((Variable)p.Param), IExpr2Expr(p.Body))).IExpr; } public AI.IFunApp! Exists(AI.AIType paramType, AI.FunctionBody! bodygen) { // generate a fresh new variable Variable! var = FreshBoundVariable(paramType); Expr! expr = IExpr2Expr(bodygen(var)); return (AI.IFunApp)(new ExistsExpr(Token.NoToken, new VariableSeq(var), expr)).IExpr; } public AI.IFunApp! Forall(AI.IFunction! p) { return (AI.IFunApp)(new ForallExpr(Token.NoToken, new VariableSeq((Variable)p.Param), IExpr2Expr(p.Body))).IExpr; } public AI.IFunApp! Forall(AI.AIType paramType, AI.FunctionBody! bodygen) { // generate a fresh new variable Variable! var = FreshBoundVariable(paramType); Expr! expr = IExpr2Expr(bodygen(var)); return (AI.IFunApp)(new ForallExpr(Token.NoToken, new VariableSeq(var), expr)).IExpr; } private static int freshVarNum = 0; private static Variable! FreshBoundVariable(AI.AIType paramType) { // TODO: Should use the AI.AIType given in Exists and Forall to determine what Boogie type // to make this new variable? For now, we use Type.Any. Type! t = Type.Int; /* if (paramType is AI.Ref) t = Type.Ref; else if (paramType is AI.FieldName) t = Type.Name; else System.Console.WriteLine("*** unsupported type in AI {0}", paramType); */ assert false; TypedIdent id = new TypedIdent(Token.NoToken, "propfactory_freshvar" + freshVarNum, t); freshVarNum++; return new BoundVariable(Token.NoToken, id); } } public class BoogieValueFactory : BoogieFactory, AI.IValueExprFactory { public AI.IFunApp! Eq(AI.IExpr! e0, AI.IExpr! e1) { return Expr.Eq(IExpr2Expr(e0), IExpr2Expr(e1)); } public AI.IFunApp! Neq(AI.IExpr! e0, AI.IExpr! e1) { return Expr.Neq(IExpr2Expr(e0), IExpr2Expr(e1)); } } public class BoogieNullnessFactory : BoogieFactory, AI.INullnessFactory { public AI.IFunApp! Eq(AI.IExpr! e0, AI.IExpr! e1) { return Expr.Eq(IExpr2Expr(e0), IExpr2Expr(e1)); } public AI.IFunApp! Neq(AI.IExpr! e0, AI.IExpr! e1) { return Expr.Neq(IExpr2Expr(e0), IExpr2Expr(e1)); } public AI.IFunApp! Null { get { assert false; // don't know where to get null from } } } public class BoogieIntFactory : BoogieValueFactory, AI.IIntExprFactory { public AI.IFunApp! Const(BigNum i) { return new LiteralExpr(Token.NoToken, i); } } public class BoogieLinearFactory : BoogieIntFactory, AI.ILinearExprFactory { public AI.IFunApp! AtMost(AI.IExpr! e0, AI.IExpr! e1) { return Expr.Le(IExpr2Expr(e0), IExpr2Expr(e1)); } public AI.IFunApp! Add(AI.IExpr! e0, AI.IExpr! e1) { return Expr.Add(IExpr2Expr(e0), IExpr2Expr(e1)); } public AI.IExpr! Term(Rational r, AI.IVariable var) { if (var != null && r == Rational.ONE) { return var; } else { Expr! product; if (r.IsIntegral) { product = Expr.Literal(r.AsBigNum); } else { product = Expr.Div(Expr.Literal(r.Numerator), Expr.Literal(r.Denominator)); } if (var != null) { product = Expr.Mul(product, IExpr2Expr(var)); } return product.IExpr; } } public AI.IFunApp! False { get { return Expr.False; } } public AI.IFunApp! True { get { return Expr.True; } } public AI.IFunApp! And(AI.IExpr! p, AI.IExpr! q) { return Expr.Binary(BinaryOperator.Opcode.And, IExpr2Expr(p), IExpr2Expr(q)); } } public class BoogieTypeFactory : BoogieFactory, AI.ITypeExprFactory { /// /// Returns an expression denoting the top of the type hierarchy. /// public AI.IExpr! RootType { get { assert false; // BUGBUG: TODO throw new System.NotImplementedException(); } } /// /// Returns true iff "t" denotes a type constant. /// [Pure] public bool IsTypeConstant(AI.IExpr! t) ensures result == (t is Constant); { return t is Constant; } /// /// Returns true iff t0 and t1 are types such that t0 and t1 are equal. /// [Pure] public bool IsTypeEqual(AI.IExpr! t0, AI.IExpr! t1) { Constant c0 = t0 as Constant; Constant c1 = t1 as Constant; return c0 != null && c1 != null && c0 == c1; } /// /// Returns true iff t0 and t1 are types such that t0 is a subtype of t1. /// [Pure] public bool IsSubType(AI.IExpr! t0, AI.IExpr! t1) { assert false; // BUGBUG: TODO } /// /// Returns the most derived supertype of both "t0" and "t1". A precondition is /// that "t0" and "t1" both represent types. /// public AI.IExpr! JoinTypes(AI.IExpr! t0, AI.IExpr! t1) { assert false; // BUGBUG: TODO } public AI.IFunApp! IsExactlyA(AI.IExpr! e, AI.IExpr! type) { //PM: We need this assume because Boogie does not yet allow us to use the //PM: inherited precondition "requires IsTypeConstant(type)". //PM: Note that that precondition is currently commented out. assume type is Constant; Constant theType = (Constant)type; assert false; Expr typeofExpr = new NAryExpr(Token.NoToken, new FunctionCall(new IdentifierExpr(Token.NoToken, "$typeof", Type.Int // Name )), new ExprSeq(IExpr2Expr(e))); return Expr.Eq(typeofExpr, Expr.Ident(theType)); } public AI.IFunApp! IsA(AI.IExpr! e, AI.IExpr! type) { //PM: We need this assume because Boogie does not yet allow us to use the //PM: inherited precondition "requires IsTypeConstant(type)". //PM: Note that that precondition is currently commented out. assume type is Constant; assert false; Expr typeofExpr = new NAryExpr(Token.NoToken, new FunctionCall(new IdentifierExpr(Token.NoToken, "$typeof", Type.Int // Name )), new ExprSeq(IExpr2Expr(e))); return new NAryExpr(Token.NoToken, new BinaryOperator(Token.NoToken, BinaryOperator.Opcode.Subtype), new ExprSeq(typeofExpr, IExpr2Expr(e))); } } }