private void DuplicateAndCheck(Expr original, IExprBuilder builder) { var duplicator = GetDuplicator(builder); var copy = (Expr)duplicator.Visit(original); // Check they are structually equal Assert.IsTrue(original.Equals(copy)); // Check the roots are different instances Assert.AreNotSame(original, copy); // Verify the nodes are disjoint, allow constants to be shared though var c = new DuplicationVerifier(/*ignoreDuplicateConstants=*/ true, /*ignoreDuplicateSymbolics=*/ false); var sharedNodes = c.CheckDuplication(original, copy); Assert.AreEqual(0, sharedNodes.Count); // Verify all nodes are immutable var iv = new ImmutableExprVerifier(); iv.Visit(copy); Assert.AreEqual(0, iv.NonImmutableNodes.Count); // Type check both Expr var TC = new TypecheckingContext(this); original.Typecheck(TC); copy.Typecheck(TC); }
public MapExecutionStateVariablesDuplicator(ExecutionState e, IExprBuilder builder) : base(builder) { this.State = e; BoundVariables = new HashSet <Variable>(); preReplacementReMap = new Dictionary <Variable, Variable>(); this.ReplaceGlobalsOnly = false; }
public override IExpr Build(BuildContext ctx, IExprBuilder initiator, Func <IExpr> next) { if (ctx.Token is ParenthesisToken openT && openT.IsOpen) { ctx.NextIndex(); IExpr innerExpr; ParenthesisToken closeT; while (true) { innerExpr = next(); ThrowIfExprIsNull(innerExpr, ctx.Token); if (ctx.Token is ParenthesisToken token && !token.IsOpen) { closeT = token; break; } ctx.PushExpr(innerExpr); } ctx.NextIndex(); return(new GroupExpr(Env) { OpenToken = openT, CloseToken = closeT, InnerExpr = innerExpr, }); } return(null); }
public override IExpr Build(BuildContext ctx, IExprBuilder initiator, Func <IExpr> next) { if (ctx.Token is NegationToken t) { ctx.NextIndex(); var nextExpr = next(); ThrowIfExprIsNull(nextExpr, t); if (nextExpr is ICanBeNegated expr) { if (!Helpers.TypesMatch(expr.ReturnType, Enums.Type.Bool)) { throw new CodeBuildEx(t.IdxS, expr.IdxE, string.Format(tr.operator__0__cannot_be_applied_to_operands_of_type__1, t, expr.ReturnType )); } return(new NegationExpr(Env) { Token = t, Expr = expr, }); } } return(null); }
public override IExpr Build(BuildContext ctx, IExprBuilder initiator, Func <IExpr> next) { if (ctx.Token is ArithmeticSymbolToken t && (t.Operation == ArithmeticOperation.Add || t.Operation == ArithmeticOperation.Subtract)) { ctx.NextIndex(); var nextExpr = next(); ThrowIfExprIsNull(nextExpr, t); if (nextExpr is ICanBePrefixedWithPlusOrMinus expr) { if (!Helpers.TypesMatch(expr.ReturnType, Enums.Type.Number)) { throw new CodeBuildEx(t.IdxS, expr.IdxE, string.Format(tr.operator__0__cannot_be_applied_to_operands_of_type__1, t, expr.ReturnType )); } return(new PlusOrMinusExpr(Env) { Token = t, Expr = expr, }); } } return(null); }
public Query WithNegatedQueryExpr(IExprBuilder builder) { var that = (Query)this.MemberwiseClone(); that.QueryExpr = this.QueryExpr.GetNegatedConstraint(builder); return(that); }
public override IExpr Build(BuildContext ctx, IExprBuilder initiator, Func <IExpr> next) { if (ctx.Token is LiteralToken t) { var func = Env.GetFunc(t.String); if (func == null) { throw new CodeBuildEx(t.IdxS, t.IdxE, string.Format( tr.the_name__0__does_not_exist_in_the_current_environment, t.String )); } ctx.NextIndex(); var funcExpr = new FuncExpr(Env) { Token = t, Func = func }; ThrowIf(ctx.Token, token => !(ctx.Token is ParenthesisToken openT) || !openT.IsOpen); funcExpr.ArgsBlockOpenToken = (ParenthesisToken)ctx.Token; ctx.NextIndex(); IExpr expr; while (true) { expr = next(); ThrowIfExprIsNull(expr, ctx.Token); if (ctx.Token is ParenthesisToken token && !token.IsOpen) { funcExpr.Args.Add(expr); funcExpr.ArgsBlockCloseToken = token; break; } if (ctx.Token is SeparatorToken) { funcExpr.Args.Add(expr); ctx.NextIndex(); continue; } ctx.PushExpr(expr); } func.ValidateArgs(Env, funcExpr.Args); ctx.NextIndex(); return(funcExpr); } return(null); }
public override IExpr Build(BuildContext ctx, IExprBuilder initiator, Func <IExpr> next) { // // `StringConcatExprBuilder` is an optimization for expressions that contains a `+` (plus), // and at least one operand of a `String` type. // String concatenations are also possible with objects of an `Any` type. Only that, those // expressions are built as `MathExpr` (since there is no way, rather than identifying type at the runtime). if (ctx.Token is ArithmeticSymbolToken t && t.Operation == Enums.ArithmeticOperation.Add) { if (initiator is StringConcatExprBuilder || ctx.BuiltExprs.Count == 0) { return(null); } var prevExpr = ctx.LastExpr; if (prevExpr.ReturnType == Enums.Type.String) { ctx.NextIndex(); var nextExpr = next(); ThrowIfExprIsNull(nextExpr, t); ctx.PopExpr(); return(new StringConcatExpr(Env) { Token = t, A = prevExpr, B = nextExpr, }); } else { if (!_applyOptimization) // try to find if B contains a string (has high computational cost) { var ctxCopy = ctx.CreateCopy(); ctx.NextIndex(); var nextExpr = next(); ThrowIfExprIsNull(nextExpr, t); if (nextExpr.ReturnType == Enums.Type.String) { ctx.PopExpr(); return(new StringConcatExpr(Env) { Token = t, A = prevExpr, B = nextExpr, }); } ctx.RestoreFrom(ctxCopy); } } } return(null); }
public void RemoveNoConstraintsBasedOnVars() { IConstraintManager CM = new ConstraintManager(); IExprBuilder builder = GetBuilder(); // Dummy Boogie variable var bv8TypeIdent = new TypedIdent(Token.NoToken, "bv8", Microsoft.Boogie.Type.GetBvType(8)); var dummyVarBv = new GlobalVariable(Token.NoToken, bv8TypeIdent); // dummyVar needs a programLocation, otherwise SymbolicVariable constructor raises an exception var progLoc = new ProgramLocation(dummyVarBv); dummyVarBv.SetMetadata <ProgramLocation>((int)Symbooglix.Annotation.AnnotationIndex.PROGRAM_LOCATION, progLoc); var s0 = new SymbolicVariable("s0", dummyVarBv).Expr; var s1 = new SymbolicVariable("s1", dummyVarBv).Expr; var s2 = new SymbolicVariable("s2", dummyVarBv).Expr; // Construct some constraints Expr c0 = builder.Eq(builder.BVAND(s0, s1), builder.ConstantBV(0, 8)); Expr c1 = builder.Eq(s2, builder.ConstantBV(1, 8)); CM.AddConstraint(c0, progLoc); CM.AddConstraint(c1, progLoc); var mockSolver = new MockSolver(); var indepenceSolver = new Symbooglix.Solver.ConstraintIndependenceSolver(mockSolver); Expr queryExpr = builder.Eq(builder.BVAND(s1, s2), builder.ConstantBV(0, 8)); indepenceSolver.ComputeSatisfiability(new Solver.Query(CM, new Constraint(queryExpr))); // Check no constraints were removed Assert.AreEqual(2, mockSolver.Constraints.Count); Assert.AreSame(queryExpr, mockSolver.QueryExpr); bool c0Found = false; bool c1Found = false; foreach (var constraint in mockSolver.Constraints) { if (c0 == constraint.Condition) { c0Found = true; } if (c1 == constraint.Condition) { c1Found = true; } } Assert.IsTrue(c0Found); Assert.IsTrue(c1Found); }
public override IExpr Build(BuildContext ctx, IExprBuilder initiator, Func <IExpr> next) { if (ctx.Token is LogicalOperatorToken t) { if (initiator is LogicalExprBuilder || ctx.BuiltExprs.Count == 0) { return(null); } var prevExpr = ctx.LastExpr; if (!Helpers.TypesMatch(prevExpr.ReturnType, Enums.Type.Bool)) { throw new CodeBuildEx(t.IdxS, t.IdxE, string.Format(tr.operator__0__cannot_be_applied_to_operands_of_type__1, t, prevExpr.ReturnType )); } ctx.NextIndex(); var hasB = false; IExpr nextExpr; while (true) { nextExpr = next(); if (!hasB) { ThrowIfExprIsNull(nextExpr, t); } if (nextExpr == null) { break; } hasB = true; ctx.PushExpr(nextExpr); } nextExpr = ctx.PopExpr(); // nextExpr ctx.PopExpr(); // prevExpr return(new LogicalExpr(Env) { Token = t, A = prevExpr, B = nextExpr, }); } return(null); }
public override IExpr Build(BuildContext ctx, IExprBuilder initiator, Func <IExpr> next) { if (ctx.Token is IConstantToken t) { ctx.NextIndex(); return(ConstantExprFactory.Create(t, Env)); } return(null); }
protected virtual IExpr Cycle(BuildContext ctx, IExprBuilder initiator = null) { for (var idx = 0; idx < Builders.Count; idx++) { var expr = Builders[idx].Build(ctx, initiator, () => Cycle(ctx, Builders[idx])); if (expr != null) { return(expr); } } return(null); }
private Dictionary <int, Dictionary <BigInteger, LiteralExpr> > BitVectorCache; // FIXME: Should probably use concurrent dictionary for thread safety public ConstantCachingExprBuilder(IExprBuilder underlyingBuilder) : base(underlyingBuilder) { // It's not safe to cache expressions if the underlying builder does not give immutable LiteralExprs if (!UB.Immutable) { throw new ArgumentException("Underlying builder must build immutable expressions"); } // Setup Caches this.CachedTrueExpr = UB.True; Debug.Assert(this.CachedTrueExpr.isBool && this.CachedTrueExpr.asBool); this.CachedFalseExpr = UB.False; Debug.Assert(this.CachedFalseExpr.isBool && !this.CachedFalseExpr.asBool); this.IntegerCache = new Dictionary <BigInteger, LiteralExpr>(); this.RealCache = new Dictionary <BigDec, LiteralExpr>(); this.BitVectorCache = new Dictionary <int, Dictionary <BigInteger, LiteralExpr> >(); }
public Constraint GetNegatedConstraint(IExprBuilder builder) { var that = (Constraint)this.MemberwiseClone(); // Optimisation: // We don't need to recompute (or copy) the set of used UF and variables // for that // Negate the Condition if (!Condition.Type.IsBool) { throw new ExprTypeCheckException("Cannot negate an expression that is not a bool"); } that.Condition = builder.Not(this.Condition); return(that); }
public override IExpr Build(BuildContext ctx, IExprBuilder initiator, Func <IExpr> next) { if (ctx.Token is ArrayParenthesisToken openT && openT.IsOpen) { ctx.NextIndex(); var arrayExpr = new ArrayExpr(Env) { OpenToken = openT, }; IExpr expr; while (true) { expr = next(); ThrowIfExprIsNull(expr, ctx.Token); if (ctx.Token is ArrayParenthesisToken token && !token.IsOpen) { arrayExpr.Elements.Add(expr); arrayExpr.CloseToken = token; break; } if (ctx.Token is SeparatorToken) { arrayExpr.Elements.Add(expr); ctx.NextIndex(); continue; } ctx.PushExpr(expr); } ctx.NextIndex(); arrayExpr.IdentifyExactReturnType(); return(arrayExpr); } return(null); }
public override IExpr Build(BuildContext ctx, IExprBuilder initiator, Func <IExpr> next) { if (ctx.Token is ComparisonToken t) { if (initiator is ConditionalExprBuilder || ctx.BuiltExprs.Count == 0) { return(null); } var prevExpr = ctx.LastExpr; ctx.NextIndex(); var nextExpr = next(); ThrowIfExprIsNull(nextExpr, t); if (!Helpers.TypesMatch(prevExpr.ReturnType, nextExpr.ReturnType)) { throw new CodeBuildEx(t.IdxS, t.IdxE, string.Format(tr.operator__0__cannot_be_applied_to_operands_of_type__1__and__2, t, prevExpr.ReturnType, nextExpr.ReturnType )); } ctx.PopExpr(); return(new ConditionalExpr(Env) { Token = t, A = prevExpr, B = nextExpr, }); } return(null); }
public TypeSynonym() { builder = new SimpleExprBuilder(/*immutable=*/ true); }
public override IExpr Build(BuildContext ctx, IExprBuilder initiator, Func <IExpr> next) { if (ctx.Token is ArithmeticSymbolToken t) { if (initiator is MathExprBuilder || ctx.BuiltExprs.Count == 0) { return(null); } var prevExpr = ctx.LastExpr; IMathExprSuperior superior = null; if (prevExpr is IMathExprSuperior) { superior = (IMathExprSuperior)prevExpr; prevExpr = superior.B; } if (!Helpers.TypesMatch(prevExpr.ReturnType, Enums.Type.Number)) { return(null); } ctx.NextIndex(); var nextExpr = next(); ThrowIfExprIsNull(nextExpr, t); if (!Helpers.TypesMatch(nextExpr.ReturnType, Enums.Type.Number)) { if (_applyStringConcatOptimization) { if (t.Operation == ArithmeticOperation.Add) { // `StringConcatExprBuilder` will only build an expr if A has a string return type if (nextExpr.ReturnType == Enums.Type.String) { ctx.PopExpr(); return(new StringConcatExpr(Env) { Token = t, A = prevExpr, B = nextExpr, }); } } } throw new CodeBuildEx(t.IdxS, t.IdxE, string.Format(tr.operator__0__cannot_be_applied_to_operands_of_type__1, t, nextExpr.ReturnType )); } ctx.PopExpr(); var mathExpr = new MathExpr(Env) { Token = t, A = prevExpr, B = nextExpr }; if (prevExpr is MathExpr prevMathExpr && Helpers.GetArithmeticOperationPriority(t.Operation) > Helpers.GetArithmeticOperationPriority(prevMathExpr.Token.Operation) ) { // rearrange expressions based on operation priority: e.g. "((1 + 1) * 10)" -> "(1 + (1 * 10))" mathExpr.A = prevMathExpr.B; prevMathExpr.B = mathExpr; // keep previous math expression as the principal one mathExpr = prevMathExpr; } if (superior != null) { superior.B = mathExpr; return(superior); } else { return(mathExpr); } } return(null); }
public Literal() { SymbooglixLibTests.SymbooglixTest.SetupDebug(); Builder = new SimpleExprBuilder(/*immutable=*/ true); }
public IBranchSatisfiabilityResult CheckBranchSatisfiability(IConstraintManager constraints, Constraint trueExpr, IExprBuilder builder) { // Note: We implicitly assume that the constraints are satisfiable TryInterupt = false; IQueryResult falseBranchResult = null; IQueryResult trueBranchResult = null; try { Timer.Start(); // Fast path: trueExpr is constant var trueExprAsLit = ExprUtil.AsLiteral(trueExpr.Condition); if (trueExprAsLit != null) { if (!trueExprAsLit.isBool) { throw new ExprTypeCheckException("trueExpr must be of boolean type"); } if (trueExprAsLit.asBool) { return(new SimpleBranchSatsifiabilityResult(Result.SAT, Result.UNSAT)); } else { return(new SimpleBranchSatsifiabilityResult(Result.UNSAT, Result.SAT)); } } // Slow path: Invoke solver // First see if it's possible for the false branch to be feasible // ∃ X constraints(X) ∧ ¬ condition(X) var query = new Solver.Query(constraints, trueExpr); falseBranchResult = InternalComputeSatisfiability(query.WithNegatedQueryExpr(builder)); var falseBranch = falseBranchResult.Satisfiability; var trueBranch = Result.UNKNOWN; // Only invoke solver again if necessary if (falseBranch == Result.UNSAT) { // This actually implies that // // ∀X : C(X) → Q(X) // That is if the constraints are satisfiable then // the query expr is always true. Because we've been // checking constraints as we go we already know C(X) is satisfiable trueBranch = Result.SAT; } else { if (TryInterupt) { // Don't do next solver call Console.Error.WriteLine("WARNING: Tried to kill solver during CheckBranchSatisfiability()"); return(new SimpleBranchSatsifiabilityResult(Result.UNKNOWN, falseBranch)); } // Now see if it's possible for execution to continue past the assertion // ∃ X constraints(X) ∧ condition(X) trueBranchResult = InternalComputeSatisfiability(query); trueBranch = trueBranchResult.Satisfiability; } return(new SimpleBranchSatsifiabilityResult(trueBranch, falseBranch)); } finally { Timer.Stop(); if (falseBranchResult != null) { UpdateStatistics(falseBranchResult); } if (trueBranchResult != null) { UpdateStatistics(trueBranchResult); } } }
public BuilderDuplicator(IExprBuilder builder) { Debug.Assert(builder != null); Builder = builder; }
private BuilderDuplicator GetDuplicator(IExprBuilder builder) { return(new BuilderDuplicator(builder)); }
public CallAssignsTo() { Builder = new SimpleExprBuilder(/*immutable=*/ true); }
public MathParserTest() { _basicExprBuilder = new ExprBuilder(); }
private void Init() { p = LoadProgramFrom("programs/SimpleCallSummary.bpl"); e = GetExecutor(p, new DFSStateScheduler(), GetSolver()); Builder = new SimpleExprBuilder(/*immutable=*/ true); }
public void RemoveNoConstraintsBasedOnVarsAndFunctions() { IConstraintManager CM = new ConstraintManager(); IExprBuilder builder = GetBuilder(); // Dummy Boogie variable var bv8Type = Microsoft.Boogie.Type.GetBvType(8); var bv8TypeIdent = new TypedIdent(Token.NoToken, "bv8", bv8Type); var dummyVarBv = new GlobalVariable(Token.NoToken, bv8TypeIdent); // dummyVar needs a programLocation, otherwise SymbolicVariable constructor raises an exception var progLoc = new ProgramLocation(dummyVarBv); dummyVarBv.SetMetadata <ProgramLocation>((int)Symbooglix.Annotation.AnnotationIndex.PROGRAM_LOCATION, progLoc); var s0 = new SymbolicVariable("s0", dummyVarBv).Expr; var s1 = new SymbolicVariable("s1", dummyVarBv).Expr; var s2 = new SymbolicVariable("s2", dummyVarBv).Expr; // Construct some constraints Expr c0 = builder.Eq(builder.BVAND(s0, s1), builder.ConstantBV(0, 8)); Expr c1 = builder.Eq(s2, builder.ConstantBV(1, 8)); var FCB = new FunctionCallBuilder(); var foobarFunc = FCB.CreateUninterpretedFunctionCall("foobar", bv8Type, new List <Microsoft.Boogie.Type>() { bv8Type }); // foobar(0bv8) == 0bv8 Expr c2 = builder.Eq(builder.UFC(foobarFunc, builder.ConstantBV(0, 8)), builder.ConstantBV(0, 8)); CM.AddConstraint(c0, progLoc); CM.AddConstraint(c1, progLoc); CM.AddConstraint(c2, progLoc); var mockSolver = new MockSolver(); var indepenceSolver = new Symbooglix.Solver.ConstraintIndependenceSolver(mockSolver); // The query expression uses the "foobar" function so we need to keep constraints on that function Expr queryExpr = builder.And(builder.Eq(builder.BVAND(s1, s2), builder.ConstantBV(0, 8)), builder.NotEq(builder.UFC(foobarFunc, s1), s1) ); indepenceSolver.ComputeSatisfiability(new Solver.Query(CM, new Constraint(queryExpr))); // Check no constraints were removed Assert.AreEqual(3, mockSolver.Constraints.Count); Assert.AreSame(queryExpr, mockSolver.QueryExpr); bool c0Found = false; bool c1Found = false; bool c2Found = false; foreach (var constraint in mockSolver.Constraints) { if (c0 == constraint.Condition) { c0Found = true; } if (c1 == constraint.Condition) { c1Found = true; } if (c2 == constraint.Condition) { c2Found = true; } } Assert.IsTrue(c0Found); Assert.IsTrue(c1Found); Assert.IsTrue(c2Found); }
public DecoratorExprBuilder(IExprBuilder underlyingBuilder) { UB = underlyingBuilder; }
public abstract IExpr Build(BuildContext ctx, IExprBuilder initiator, Func <IExpr> next);