/// <summary> /// Yield an expression that is 'inexpr' with 'var' replaced by 'subst'. /// </summary> /// <param name="subst">The expression to substitute.</param> /// <param name="var">The variable to substitute for.</param> /// <param name="inexpr">The expression to substitute into.</param> public static IExpr /*!*/ Substitute(IExpr /*!*/ subst, IVariable /*!*/ var, IExpr /*!*/ inexpr) { Contract.Requires(inexpr != null); Contract.Requires(var != null); Contract.Requires(subst != null); Contract.Ensures(Contract.Result <IExpr>() != null); IExpr result = null; if (inexpr is IVariable) { result = inexpr.Equals(var) ? subst : inexpr; } else if (inexpr is IFunApp) { IFunApp /*!*/ funapp = (IFunApp /*!*/)cce.NonNull(inexpr); IList newargs = null; var x = new System.Collections.Generic.List <IExpr>(); foreach (IExpr arg in funapp.Arguments) { x.Add(Substitute(subst, var, arg)); } newargs = new ArrayList(x); //newargs = new ArrayList{ IExpr/*!*/ arg in funapp.Arguments; Substitute(subst, var, arg) }; result = funapp.CloneWithArguments(newargs); } else if (inexpr is IFunction) { IFunction /*!*/ fun = (IFunction /*!*/)cce.NonNull(inexpr); if (fun.Param.Equals(var)) { result = fun; } else { result = fun.CloneWithBody(Substitute(subst, var, fun.Body)); } } else if (inexpr is IUnknown) { result = inexpr; } else { { Contract.Assert(false); throw new cce.UnreachableException(); } } return(result); }
/// <summary> /// Return a new expression in which each variable has been /// replaced by an expression representing what is known about /// that variable. /// </summary> private IExpr /*!*/ InlineVariables(Elt /*!*/ element, IExpr /*!*/ expr, ISet /*<IVariable!>*//*!*/ notInlineable, OnUnableToInline /*!*/ unableToInline) { Contract.Requires(unableToInline != null); Contract.Requires(notInlineable != null); Contract.Requires(expr != null); Contract.Requires(element != null); Contract.Ensures(Contract.Result <IExpr>() != null); IVariable var = expr as IVariable; if (var != null) { /*MicroLattice*/ Element value = element[var]; if (notInlineable.Contains(var) || value == null || this.microLattice.IsTop(value)) { return(unableToInline(var)); // We don't know anything about this variable. } else { // GetFoldExpr returns null when it can yield an expression that // can be substituted for the variable. IExpr valueExpr = this.microLattice.GetFoldExpr(value); return((valueExpr == null) ? var : valueExpr); } } // else IFunApp fun = expr as IFunApp; if (fun != null) { IList newargs = new ArrayList(); foreach (IExpr /*!*/ arg in fun.Arguments) { Contract.Assert(arg != null); newargs.Add(InlineVariables(element, arg, notInlineable, unableToInline)); } return(fun.CloneWithArguments(newargs)); } // else IFunction lambda = expr as IFunction; if (lambda != null) { IMutableSet x = new HashSet(1); x.Add(lambda.Param); // Don't inline the bound variable return(lambda.CloneWithBody( InlineVariables(element, lambda.Body, cce.NonNull(Set.Union(notInlineable, x)), unableToInline) )); } // else if (expr is IUnknown) { return(expr); } else { throw new System.NotImplementedException("cannot inline identifies in expression " + expr); } }