summaryrefslogtreecommitdiff
path: root/Source/AIFramework/VariableMap/ConstantExpressions.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Source/AIFramework/VariableMap/ConstantExpressions.cs')
-rw-r--r--Source/AIFramework/VariableMap/ConstantExpressions.cs1056
1 files changed, 528 insertions, 528 deletions
diff --git a/Source/AIFramework/VariableMap/ConstantExpressions.cs b/Source/AIFramework/VariableMap/ConstantExpressions.cs
index fcf49b25..185c700e 100644
--- a/Source/AIFramework/VariableMap/ConstantExpressions.cs
+++ b/Source/AIFramework/VariableMap/ConstantExpressions.cs
@@ -1,538 +1,538 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
- /////////////////////////////////////////////////////////////////////////////////
- // The Abstract domain for determining "constant" expressions
- // i.e. It determines which expression are statically binded
- /////////////////////////////////////////////////////////////////////////////////
-/*
-using System;
-
-namespace Microsoft.AbstractInterpretationFramework
-{
- using Microsoft.Contracts;
- using System.Collections.Generic;
- using Microsoft.AbstractInterpretationFramework;
-
- /// <summary>
- /// This is an abstract domain for inferring constant expressions
- /// </summary>
-
- public class ConstantExpressions : Lattice
- {
- /// <summary>
- /// An abstract element is made of two maps:
- /// + A map from variables to expressions \cup top ( i.e. for each variable, the expression it is binded )
- /// + A map from variables to set of variabes ( i.e. for each variable, the set of variables that depends on its value )
- /// </summary>
- private class AbstractElement: Element
- {
- private Dictionary<IVariable!, BindExpr> variableBindings;
- private Dictionary<IVariable!, List<IVariable>> variableDependences;
-
- static private AbstractElement! bottom;
- static public Element! Bottom
- {
- get
- {
- if(bottom == null)
- {
- bottom = new AbstractElement();
- bottom.variableBindings = null;
- bottom.variableDependences = null;
- }
- assert bottom.variableBindings == null && bottom.variableDependences == null;
- return bottom;
- }
- }
-
- static public Element! Top
- {
- get
- {
- return new AbstractElement();
- }
- }
-
- AbstractElement()
- {
- this.variableBindings = new Dictionary<IVariable!, BindExpr>();
- this.variableDependences = new Dictionary<IVariable!, List<IVariable>>();
- }
-
- /// <summary>
- /// Our abstract element is top if and only if it has any constraint on variables
- /// </summary>
- public bool IsTop
- {
- get
- {
- return this.variableBindings.Keys.Count == 0 && this.variableDependences.Keys.Count == 0;
- }
- }
-
- /// <summary>
- /// Our abstract element is bottom if and only if the maps are null
- /// </summary>
- public bool IsBottom
- {
- get
- {
- assert (this.variableBindings == null) <==> (this.variableDependences == null);
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // The Abstract domain for determining "constant" expressions
+ // i.e. It determines which expression are statically binded
+ /////////////////////////////////////////////////////////////////////////////////
+/*
+using System;
+
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using Microsoft.Contracts;
+ using System.Collections.Generic;
+ using Microsoft.AbstractInterpretationFramework;
+
+ /// <summary>
+ /// This is an abstract domain for inferring constant expressions
+ /// </summary>
+
+ public class ConstantExpressions : Lattice
+ {
+ /// <summary>
+ /// An abstract element is made of two maps:
+ /// + A map from variables to expressions \cup top ( i.e. for each variable, the expression it is binded )
+ /// + A map from variables to set of variabes ( i.e. for each variable, the set of variables that depends on its value )
+ /// </summary>
+ private class AbstractElement: Element
+ {
+ private Dictionary<IVariable!, BindExpr> variableBindings;
+ private Dictionary<IVariable!, List<IVariable>> variableDependences;
+
+ static private AbstractElement! bottom;
+ static public Element! Bottom
+ {
+ get
+ {
+ if(bottom == null)
+ {
+ bottom = new AbstractElement();
+ bottom.variableBindings = null;
+ bottom.variableDependences = null;
+ }
+ assert bottom.variableBindings == null && bottom.variableDependences == null;
+ return bottom;
+ }
+ }
+
+ static public Element! Top
+ {
+ get
+ {
+ return new AbstractElement();
+ }
+ }
+
+ AbstractElement()
+ {
+ this.variableBindings = new Dictionary<IVariable!, BindExpr>();
+ this.variableDependences = new Dictionary<IVariable!, List<IVariable>>();
+ }
+
+ /// <summary>
+ /// Our abstract element is top if and only if it has any constraint on variables
+ /// </summary>
+ public bool IsTop
+ {
+ get
+ {
+ return this.variableBindings.Keys.Count == 0 && this.variableDependences.Keys.Count == 0;
+ }
+ }
+
+ /// <summary>
+ /// Our abstract element is bottom if and only if the maps are null
+ /// </summary>
+ public bool IsBottom
+ {
+ get
+ {
+ assert (this.variableBindings == null) <==> (this.variableDependences == null);
return this.variableBindings == null && this.variableDependences == null;
- }
- }
-
- /// <summary>
- /// The pointwise join...
- /// </summary>
- public static AbstractElement! Join(AbstractElement! left, AbstractElement! right)
- {
+ }
+ }
+
+ /// <summary>
+ /// The pointwise join...
+ /// </summary>
+ public static AbstractElement! Join(AbstractElement! left, AbstractElement! right)
+ {
AbstractElement! result = new AbstractElement();
-
- // Put all the variables in the left
- foreach(IVariable! var in left.variableBindings.Keys)
- {
- BindExpr leftVal = left.variableBindings[var];
- assert leftVal != null;
-
- BindExpr rightVal = right.variableBindings[var];
-
- if(rightVal== null) // the expression is not there
- {
+
+ // Put all the variables in the left
+ foreach(IVariable! var in left.variableBindings.Keys)
+ {
+ BindExpr leftVal = left.variableBindings[var];
+ assert leftVal != null;
+
+ BindExpr rightVal = right.variableBindings[var];
+
+ if(rightVal== null) // the expression is not there
+ {
result.variableBindings.Add(var, leftVal);
- }
- else // both abstract elements have a definition for the variable....
- {
- result.variableBindings.Add(var, BindExpr.Join(leftVal, rightVal));
- }
- }
-
- // Put all the variables in the right
- foreach(IVariable! var in right.variableBindings.Keys)
- {
- BindExpr rightVal = right.variableBindings[var];
- assert rightVal != null;
-
- BindExpr leftVal = left.variableBindings[var];
-
- if(rightVal== null) // the expression is not there
- {
+ }
+ else // both abstract elements have a definition for the variable....
+ {
+ result.variableBindings.Add(var, BindExpr.Join(leftVal, rightVal));
+ }
+ }
+
+ // Put all the variables in the right
+ foreach(IVariable! var in right.variableBindings.Keys)
+ {
+ BindExpr rightVal = right.variableBindings[var];
+ assert rightVal != null;
+
+ BindExpr leftVal = left.variableBindings[var];
+
+ if(rightVal== null) // the expression is not there
+ {
result.variableBindings.Add(var, rightVal);
- }
- else // both abstract elements have a definition for the variable....
- {
- result.variableBindings.Add(var, BindExpr.Join(rightVal, leftVal));
- }
- }
-
- // Join the dependencies...
- foreach(IVariable! var in left.variableDependences.Keys)
- {
- List<IVariable> dependencies = left.variableDependences[var];
- List<IVariable> dup = new List<IVariable>(dependencies);
-
- result.variableDependences.Add(var, dup);
- }
-
- foreach(IVariable! var in right.variableDependences.Keys)
- {
- if(result.variableDependences.ContainsKey(var))
- {
- List<IVariable> dependencies = result.variableDependences[var];
- dependencies.AddRange(right.variableDependences[var]);
- }
- else
- {
- List<IVariable> dependencies = right.variableDependences[var];
- List<IVariable> dup = new List<IVariable>(dependencies);
-
- result.variableDependences.Add(var, dup);
- }
- }
-
- // Normalize... i.e. for the variables such thas they point to an unknown expression (top) we have to update also their values
- result.Normalize();
-
- return result;
- }
-
-
- ///<summary>
- /// Normalize the current abstract element, in that it propagetes the "dynamic" information throughtout the abstract element
- ///</summary>
- public void Normalize()
- {
- if(this.IsBottom)
- return;
- if(this.IsTop)
- return;
- assert this.variableBindings != null;
-
- bool atFixpoint = false;
-
- while(!atFixpoint)
- {
- atFixpoint = true; // guess that we've got the fixpoint...
-
- foreach(IVariable x in this.variableBindings.Keys)
- {
- if(this.variableBindings[x].IsTop) // It means that the variable is tied to a dynamic expression
- {
- foreach(IVariable y in this.variableDependences[x]) // The all the variables that depend on x are also dynamic...
- {
- assert x != y; // A variable cannot depend on itself...
- if(!this.variableBindings[y].IsTop)
- {
- this.variableBindings[y] = BindExpr.Top;
- atFixpoint = false; // the assumption that we were at the fixpoint was false, we have still to propagate some information...
- }
- }
- }
- }
- }
- }
-
- /// <summary>
- /// The pointwise meet...
- /// </summary>
- public static AbstractElement! Meet(AbstractElement! left, AbstractElement! right)
- {
- AbstractElement! result = new AbstractElement();
-
- // Put the variables that are both in left and right
- foreach(IVariable var in left.variableBindings.Keys)
- {
- if(right.variableBindings.ContainsKey(var))
- {
- result.variableBindings.Add(var, BindExpr.Meet(left.variableBindings[var], right.variableBindings[var]));
- }
- }
-
- // Intersect the dependencies
- foreach(IVariable var in result.variableBindings.Keys)
- {
- List<IVariable> depLeft = left.variableDependences[var];
- List<IVariable> depRight = right.variableDependences[var];
-
- // Intersect the two sets
+ }
+ else // both abstract elements have a definition for the variable....
+ {
+ result.variableBindings.Add(var, BindExpr.Join(rightVal, leftVal));
+ }
+ }
+
+ // Join the dependencies...
+ foreach(IVariable! var in left.variableDependences.Keys)
+ {
+ List<IVariable> dependencies = left.variableDependences[var];
+ List<IVariable> dup = new List<IVariable>(dependencies);
+
+ result.variableDependences.Add(var, dup);
+ }
+
+ foreach(IVariable! var in right.variableDependences.Keys)
+ {
+ if(result.variableDependences.ContainsKey(var))
+ {
+ List<IVariable> dependencies = result.variableDependences[var];
+ dependencies.AddRange(right.variableDependences[var]);
+ }
+ else
+ {
+ List<IVariable> dependencies = right.variableDependences[var];
+ List<IVariable> dup = new List<IVariable>(dependencies);
+
+ result.variableDependences.Add(var, dup);
+ }
+ }
+
+ // Normalize... i.e. for the variables such thas they point to an unknown expression (top) we have to update also their values
+ result.Normalize();
+
+ return result;
+ }
+
+
+ ///<summary>
+ /// Normalize the current abstract element, in that it propagetes the "dynamic" information throughtout the abstract element
+ ///</summary>
+ public void Normalize()
+ {
+ if(this.IsBottom)
+ return;
+ if(this.IsTop)
+ return;
+ assert this.variableBindings != null;
+
+ bool atFixpoint = false;
+
+ while(!atFixpoint)
+ {
+ atFixpoint = true; // guess that we've got the fixpoint...
+
+ foreach(IVariable x in this.variableBindings.Keys)
+ {
+ if(this.variableBindings[x].IsTop) // It means that the variable is tied to a dynamic expression
+ {
+ foreach(IVariable y in this.variableDependences[x]) // The all the variables that depend on x are also dynamic...
+ {
+ assert x != y; // A variable cannot depend on itself...
+ if(!this.variableBindings[y].IsTop)
+ {
+ this.variableBindings[y] = BindExpr.Top;
+ atFixpoint = false; // the assumption that we were at the fixpoint was false, we have still to propagate some information...
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// The pointwise meet...
+ /// </summary>
+ public static AbstractElement! Meet(AbstractElement! left, AbstractElement! right)
+ {
+ AbstractElement! result = new AbstractElement();
+
+ // Put the variables that are both in left and right
+ foreach(IVariable var in left.variableBindings.Keys)
+ {
+ if(right.variableBindings.ContainsKey(var))
+ {
+ result.variableBindings.Add(var, BindExpr.Meet(left.variableBindings[var], right.variableBindings[var]));
+ }
+ }
+
+ // Intersect the dependencies
+ foreach(IVariable var in result.variableBindings.Keys)
+ {
+ List<IVariable> depLeft = left.variableDependences[var];
+ List<IVariable> depRight = right.variableDependences[var];
+
+ // Intersect the two sets
result.variableDependences.Add(var, depLeft);
- foreach(IVariable v in depRight)
- {
- if(!result.variableDependences.ContainsKey(v))
- {
+ foreach(IVariable v in depRight)
+ {
+ if(!result.variableDependences.ContainsKey(v))
+ {
result.variableDependences.Remove(v);
- }
- }
- }
-
- // Now we remove the dependencies with variables not in variableBindings
+ }
+ }
+ }
+
+ // Now we remove the dependencies with variables not in variableBindings
List<IVariable>! varsToRemove = new List<IVariable>();
-
- foreach(IVariable var in result.
-
-
- }
-
- /// <summary>
- /// Clone the current abstract element
- /// </summary>
- public override Element! Clone()
- {
- AbstractElement cloned = new AbstractElement();
- foreach(IVariable var in this.variableBindings.Keys)
- {
- cloned.variableBindings.Add(var, this.variableBindings[var]);
- }
-
- foreach(IVariable var in this.variableDependences.Keys)
- {
- List<IVariable> dependingVars = this.variableDependences[var];
- List<IVariable> clonedDependingVars = new List<IVariable>(dependingVars);
+
+ foreach(IVariable var in result.
+
+
+ }
+
+ /// <summary>
+ /// Clone the current abstract element
+ /// </summary>
+ public override Element! Clone()
+ {
+ AbstractElement cloned = new AbstractElement();
+ foreach(IVariable var in this.variableBindings.Keys)
+ {
+ cloned.variableBindings.Add(var, this.variableBindings[var]);
+ }
+
+ foreach(IVariable var in this.variableDependences.Keys)
+ {
+ List<IVariable> dependingVars = this.variableDependences[var];
+ List<IVariable> clonedDependingVars = new List<IVariable>(dependingVars);
cloned.variableDependences.Add(var, clonedDependingVars);
- }
- }
-
- /// <summary>
- /// Return the variables that have a binding
- /// </summary>
- public override ICollection<IVariable!>! FreeVariables()
- {
- List<IVariable!> vars = new List<IVariable!>(this.variableBindings.Keys);
-
- return vars;
- }
-
- public override string! ToString()
- {
+ }
+ }
+
+ /// <summary>
+ /// Return the variables that have a binding
+ /// </summary>
+ public override ICollection<IVariable!>! FreeVariables()
+ {
+ List<IVariable!> vars = new List<IVariable!>(this.variableBindings.Keys);
+
+ return vars;
+ }
+
+ public override string! ToString()
+ {
string! retString = "";
- retString += "Bindings";
-
- foreach(IVariable var in this.variableBindings.Keys)
- {
- string! toAdd = var.ToString() + " -> " + this.variableBindings[var];
- retString += toAdd + ",";
- }
-
- retString += "\nDependencies";
- foreach(IVariable var in this.variableDependences.Keys)
- {
- string! toAdd = var.ToString() + " -> " + this.variableDependences[var];
- retString += toAdd + ",";
- }
-
- return retString;
- }
- }
-
- public override Element! Top
- {
- get
- {
- return AbstractElement.Top;
- }
- }
-
- public override Element! Bottom
- {
- get
- {
- return AbstractElement.Bottom;
- }
- }
-
- public override bool IsTop(Element! e)
- {
- assert e is AbstractElement;
- AbstractElement! absElement = (AbstractElement) e;
-
- return absElement.IsTop;
- }
-
- public override bool IsBottom(Element! e)
- {
- assert e is AbstractElement;
- AbstractElement absElement = (AbstractElement) e;
- return absElement.IsBottom;
- }
-
- /// <summary>
- /// Perform the pointwise join of the two abstract elements
- /// </summary>
- public override Element! NontrivialJoin(Element! a, Element! b)
- {
- assert a is AbstractElement;
- assert b is AbstractElement;
-
- AbstractElement! left = (AbstractElement!) a;
- AbstractElement! right = (AbstractElement!) b;
-
- return AbstractElement.Join(left, right);
- }
-
- /// <summary>
- /// Perform the pointwise meet of two abstract elements
- /// </summary>
- public override Element! NontrivialMeet(Element! a, Element!b)
- {
- assert a is AbstractElement;
- assert b is AbstractElement;
-
- AbstractElement! left = (AbstractElement!) a;
- AbstractElement! right = (AbstractElement!) b;
-
- return AbstractElement.Meet(left, right);
- }
-
-
- }
-
- /// <summary>
- /// A wrapper in order to have the algebraic datatype BindExpr := IExpr | Top
- /// </summary>
- abstract class BindExpr
- {
- /// <summary>
- /// True iff this expression is instance of BindExprTop
- /// </summary>
- public bool IsTop
- {
- get
- {
- return this is BindExprTop;
- }
- }
-
- static public BindExpr Top
- {
- get
- {
- return BindExprTop.UniqueTop;
- }
- }
-
- /// <summary>
- /// True iff this expression is instance of BindExprBottom
- /// </summary>
- public bool IsBottom
- {
- get
- {
- return this is BindExprBottom;
- }
- }
-
- static public BindExpr Bottom
- {
- get
- {
- return BindExprBottom.UniqueBottom;
- }
- }
-
- public static BindExpr! Join(BindExpr! left, BindExpr! right)
- {
- if(left.IsTop || right.IsTop)
- {
- return BindExpr.Top;
- }
- else if(left.IsBottom)
- {
- return right;
- }
- else if(right.IsBottom)
- {
- return left;
- }
- else if(left.EmbeddedExpr != right.EmbeddedExpr)
- {
- return BindExpr.Top;
- }
- else // left.EmbeddedExpr == right.EmbeddedExpr
- {
- return left;
- }
- }
-
- public static BindExpr! Meet(BindExpr! left, BindExpr! right)
- {
- if(left.IsTop)
- {
- return right;
- }
- else if(right.IsTop)
- {
- return right;
- }
- else if(left.IsBottom || right.IsBottom)
- {
- return BindExpr.Bottom;
- }
- else if(left.EmbeddedExpr != right.EmbeddedExpr)
- {
- return BindExpr.Bottom;
- }
- else // left.EmbeddedExpr == right.EmbeddedExpr
- {
- return left;
- }
- }
-
- abstract public IExpr! EmbeddedExpr
- {
- get;
- }
-
- }
-
- /// <summary>
- /// A wrapper for an integer
- /// </summary>
- class Expr : BindExpr
- {
- private IExpr! exp;
-
- public Expr(IExpr! exp)
- {
- this.exp = exp;
- }
-
- override public IExpr! EmbeddedExpr
- {
- get
- {
- return this.exp;
- }
- }
-
- public override string! ToString()
- {
- return this.exp.ToString();
- }
- }
-
- /// <summary>
- /// The dynamic expression
- /// </summary>
- class BindExprTop : BindExpr
- {
- private BindExprTop top = new BindExprTop();
- static public BindExprTop! UniqueTop
- {
- get
- {
- return this.top;
- }
- }
-
- private BindExprTop() {}
-
- override public IExpr! EmbeddedExpr
- {
- get
- {
- assert false; // If we get there, we have an error
- }
- }
-
- public override string! ToString()
- {
- return "<dynamic expression>";
- }
- }
-
- /// <summary>
- /// The unreachable expression
- /// </summary>
- class BindExprBottom : BindExpr
- {
- private BindExprBottom! bottom = new BindExprBottom();
- static public BindExprBottom! UniqueBottom
- {
- get
- {
- return this.bottom;
- }
- }
-
- private BindExprBottom() {}
-
- override public IExpr! EmbeddedExpr
- {
- get
- {
- assert false;
- }
- }
-
- public override string! ToString()
- {
- return "<unreachable expression>";
- }
- }
-
-} // end namespace Microsoft.AbstractInterpretationFramework
+ retString += "Bindings";
+
+ foreach(IVariable var in this.variableBindings.Keys)
+ {
+ string! toAdd = var.ToString() + " -> " + this.variableBindings[var];
+ retString += toAdd + ",";
+ }
+
+ retString += "\nDependencies";
+ foreach(IVariable var in this.variableDependences.Keys)
+ {
+ string! toAdd = var.ToString() + " -> " + this.variableDependences[var];
+ retString += toAdd + ",";
+ }
+
+ return retString;
+ }
+ }
+
+ public override Element! Top
+ {
+ get
+ {
+ return AbstractElement.Top;
+ }
+ }
+
+ public override Element! Bottom
+ {
+ get
+ {
+ return AbstractElement.Bottom;
+ }
+ }
+
+ public override bool IsTop(Element! e)
+ {
+ assert e is AbstractElement;
+ AbstractElement! absElement = (AbstractElement) e;
+
+ return absElement.IsTop;
+ }
+
+ public override bool IsBottom(Element! e)
+ {
+ assert e is AbstractElement;
+ AbstractElement absElement = (AbstractElement) e;
+ return absElement.IsBottom;
+ }
+
+ /// <summary>
+ /// Perform the pointwise join of the two abstract elements
+ /// </summary>
+ public override Element! NontrivialJoin(Element! a, Element! b)
+ {
+ assert a is AbstractElement;
+ assert b is AbstractElement;
+
+ AbstractElement! left = (AbstractElement!) a;
+ AbstractElement! right = (AbstractElement!) b;
+
+ return AbstractElement.Join(left, right);
+ }
+
+ /// <summary>
+ /// Perform the pointwise meet of two abstract elements
+ /// </summary>
+ public override Element! NontrivialMeet(Element! a, Element!b)
+ {
+ assert a is AbstractElement;
+ assert b is AbstractElement;
+
+ AbstractElement! left = (AbstractElement!) a;
+ AbstractElement! right = (AbstractElement!) b;
+
+ return AbstractElement.Meet(left, right);
+ }
+
+
+ }
+
+ /// <summary>
+ /// A wrapper in order to have the algebraic datatype BindExpr := IExpr | Top
+ /// </summary>
+ abstract class BindExpr
+ {
+ /// <summary>
+ /// True iff this expression is instance of BindExprTop
+ /// </summary>
+ public bool IsTop
+ {
+ get
+ {
+ return this is BindExprTop;
+ }
+ }
+
+ static public BindExpr Top
+ {
+ get
+ {
+ return BindExprTop.UniqueTop;
+ }
+ }
+
+ /// <summary>
+ /// True iff this expression is instance of BindExprBottom
+ /// </summary>
+ public bool IsBottom
+ {
+ get
+ {
+ return this is BindExprBottom;
+ }
+ }
+
+ static public BindExpr Bottom
+ {
+ get
+ {
+ return BindExprBottom.UniqueBottom;
+ }
+ }
+
+ public static BindExpr! Join(BindExpr! left, BindExpr! right)
+ {
+ if(left.IsTop || right.IsTop)
+ {
+ return BindExpr.Top;
+ }
+ else if(left.IsBottom)
+ {
+ return right;
+ }
+ else if(right.IsBottom)
+ {
+ return left;
+ }
+ else if(left.EmbeddedExpr != right.EmbeddedExpr)
+ {
+ return BindExpr.Top;
+ }
+ else // left.EmbeddedExpr == right.EmbeddedExpr
+ {
+ return left;
+ }
+ }
+
+ public static BindExpr! Meet(BindExpr! left, BindExpr! right)
+ {
+ if(left.IsTop)
+ {
+ return right;
+ }
+ else if(right.IsTop)
+ {
+ return right;
+ }
+ else if(left.IsBottom || right.IsBottom)
+ {
+ return BindExpr.Bottom;
+ }
+ else if(left.EmbeddedExpr != right.EmbeddedExpr)
+ {
+ return BindExpr.Bottom;
+ }
+ else // left.EmbeddedExpr == right.EmbeddedExpr
+ {
+ return left;
+ }
+ }
+
+ abstract public IExpr! EmbeddedExpr
+ {
+ get;
+ }
+
+ }
+
+ /// <summary>
+ /// A wrapper for an integer
+ /// </summary>
+ class Expr : BindExpr
+ {
+ private IExpr! exp;
+
+ public Expr(IExpr! exp)
+ {
+ this.exp = exp;
+ }
+
+ override public IExpr! EmbeddedExpr
+ {
+ get
+ {
+ return this.exp;
+ }
+ }
+
+ public override string! ToString()
+ {
+ return this.exp.ToString();
+ }
+ }
+
+ /// <summary>
+ /// The dynamic expression
+ /// </summary>
+ class BindExprTop : BindExpr
+ {
+ private BindExprTop top = new BindExprTop();
+ static public BindExprTop! UniqueTop
+ {
+ get
+ {
+ return this.top;
+ }
+ }
+
+ private BindExprTop() {}
+
+ override public IExpr! EmbeddedExpr
+ {
+ get
+ {
+ assert false; // If we get there, we have an error
+ }
+ }
+
+ public override string! ToString()
+ {
+ return "<dynamic expression>";
+ }
+ }
+
+ /// <summary>
+ /// The unreachable expression
+ /// </summary>
+ class BindExprBottom : BindExpr
+ {
+ private BindExprBottom! bottom = new BindExprBottom();
+ static public BindExprBottom! UniqueBottom
+ {
+ get
+ {
+ return this.bottom;
+ }
+ }
+
+ private BindExprBottom() {}
+
+ override public IExpr! EmbeddedExpr
+ {
+ get
+ {
+ assert false;
+ }
+ }
+
+ public override string! ToString()
+ {
+ return "<unreachable expression>";
+ }
+ }
+
+} // end namespace Microsoft.AbstractInterpretationFramework
*/ \ No newline at end of file