//----------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- namespace Microsoft.Boogie.AbstractInterpretation { using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.Contracts; using AI = Microsoft.AbstractInterpretationFramework; using Boogie = Microsoft.Boogie; /// /// A visitor of an abstract interpretation expression that collects the free variables /// class FreeVariablesVisitor : AI.ExprVisitor { [Peer] List variables; [ContractInvariantMethod] void ObjectInvariant() { Contract.Invariant(cce.NonNullElements(variables)); Contract.Invariant(cce.NonNullElements(varNames)); } public List FreeVariables { get { Contract.Ensures(cce.NonNullElements(Contract.Result>())); return this.variables; } } List varNames; // used to check the consinstency! public FreeVariablesVisitor() { this.variables = new List(); this.varNames = new List(); } override public object Default(AI.IExpr expr) { Contract.Requires(expr != null); if (expr is AI.IVariable) { if (!variables.Contains((AI.IVariable)expr)) { this.variables.Add((AI.IVariable)expr); Contract.Assert(!this.varNames.Contains(expr.ToString())); // If we get there, we have an error: two variables with the same name but different identity this.varNames.Add(expr.ToString()); } return null; } else if (expr is AI.IFunApp) return VisitFunApp((AI.IFunApp)expr); else if (expr is AI.IFunction) return VisitFunction((AI.IFunction)expr); else { Contract.Assert(false); throw new cce.UnreachableException(); } } public override object VisitFunApp(AI.IFunApp funapp) { Contract.Requires(funapp != null); foreach (AI.IExpr arg in funapp.Arguments) { Contract.Assert(arg != null); arg.DoVisit(this); } return true; } public override object VisitFunction(AI.IFunction fun) { Contract.Requires(fun != null); fun.Body.DoVisit(this); this.variables.Remove(fun.Param); return true; } } }