Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Ast / ExpressionVisitor.cs / 1305376 / ExpressionVisitor.cs
/* **************************************************************************** * * Copyright (c) Microsoft Corporation. * * This source code is subject to terms and conditions of the Microsoft Public License. A * copy of the license can be found in the License.html file at the root of this distribution. If * you cannot locate the Microsoft Public License, please send an email to * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound * by the terms of the Microsoft Public License. * * You must not remove this notice, or any other, from this software. * * * ***************************************************************************/ using System.Collections.ObjectModel; using System.Diagnostics; using System.Dynamic.Utils; using System.Runtime.CompilerServices; #if SILVERLIGHT using System.Core; #endif namespace System.Linq.Expressions { ////// Represents a visitor or rewriter for expression trees. /// ////// This class is designed to be inherited to create more specialized /// classes whose functionality requires traversing, examining or copying /// an expression tree. /// public abstract class ExpressionVisitor { ////// Initializes a new instance of protected ExpressionVisitor() { } ///. /// /// Dispatches the expression to one of the more specialized visit methods in this class. /// /// The expression to visit. ///The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. public virtual Expression Visit(Expression node) { if (node != null) { return node.Accept(this); } return null; } ////// Dispatches the list of expressions to one of the more specialized visit methods in this class. /// /// The expressions to visit. ///The modified expression list, if any of the elements were modified; /// otherwise, returns the original expression list. public ReadOnlyCollectionVisit(ReadOnlyCollection nodes) { Expression[] newNodes = null; for (int i = 0, n = nodes.Count; i < n; i++) { Expression node = Visit(nodes[i]); if (newNodes != null) { newNodes[i] = node; } else if (!object.ReferenceEquals(node, nodes[i])) { newNodes = new Expression[n]; for (int j = 0; j < i; j++) { newNodes[j] = nodes[j]; } newNodes[i] = node; } } if (newNodes == null) { return nodes; } return new TrueReadOnlyCollection (newNodes); } internal Expression[] VisitArguments(IArgumentProvider nodes) { Expression[] newNodes = null; for (int i = 0, n = nodes.ArgumentCount; i < n; i++) { Expression curNode = nodes.GetArgument(i); Expression node = Visit(curNode); if (newNodes != null) { newNodes[i] = node; } else if (!object.ReferenceEquals(node, curNode)) { newNodes = new Expression[n]; for (int j = 0; j < i; j++) { newNodes[j] = nodes.GetArgument(j); } newNodes[i] = node; } } return newNodes; } /// /// Visits all nodes in the collection using a specified element visitor. /// ///The type of the nodes. /// The nodes to visit. /// A delegate that visits a single element, /// optionally replacing it with a new element. ///The modified node list, if any of the elements were modified; /// otherwise, returns the original node list. public static ReadOnlyCollectionVisit (ReadOnlyCollection nodes, Func elementVisitor) { T[] newNodes = null; for (int i = 0, n = nodes.Count; i < n; i++) { T node = elementVisitor(nodes[i]); if (newNodes != null) { newNodes[i] = node; } else if (!object.ReferenceEquals(node, nodes[i])) { newNodes = new T[n]; for (int j = 0; j < i; j++) { newNodes[j] = nodes[j]; } newNodes[i] = node; } } if (newNodes == null) { return nodes; } return new TrueReadOnlyCollection (newNodes); } /// /// Visits an expression, casting the result back to the original expression type. /// ///The type of the expression. /// The expression to visit. /// The name of the calling method; used to report to report a better error message. ///The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. ///The visit method for this node returned a different type. public T VisitAndConvert(T node, string callerName) where T : Expression { if (node == null) { return null; } node = Visit(node) as T; if (node == null) { throw Error.MustRewriteToSameNode(callerName, typeof(T), callerName); } return node; } /// /// Visits an expression, casting the result back to the original expression type. /// ///The type of the expression. /// The expression to visit. /// The name of the calling method; used to report to report a better error message. ///The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. ///The visit method for this node returned a different type. public ReadOnlyCollectionVisitAndConvert (ReadOnlyCollection nodes, string callerName) where T : Expression { T[] newNodes = null; for (int i = 0, n = nodes.Count; i < n; i++) { T node = Visit(nodes[i]) as T; if (node == null) { throw Error.MustRewriteToSameNode(callerName, typeof(T), callerName); } if (newNodes != null) { newNodes[i] = node; } else if (!object.ReferenceEquals(node, nodes[i])) { newNodes = new T[n]; for (int j = 0; j < i; j++) { newNodes[j] = nodes[j]; } newNodes[i] = node; } } if (newNodes == null) { return nodes; } return new TrueReadOnlyCollection (newNodes); } /// /// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitBinary(BinaryExpression node) { // Walk children in evaluation order: left, conversion, right return ValidateBinary( node, node.Update( Visit(node.Left), VisitAndConvert(node.Conversion, "VisitBinary"), Visit(node.Right) ) ); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitBlock(BlockExpression node) { int count = node.ExpressionCount; Expression[] nodes = null; for (int i = 0; i < count; i++) { Expression oldNode = node.GetExpression(i); Expression newNode = Visit(oldNode); if (oldNode != newNode) { if (nodes == null) { nodes = new Expression[count]; } nodes[i] = newNode; } } var v = VisitAndConvert(node.Variables, "VisitBlock"); if (v == node.Variables && nodes == null) { return node; } else { for (int i = 0; i < count; i++) { if (nodes[i] == null) { nodes[i] = node.GetExpression(i); } } } return node.Rewrite(v, nodes); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitConditional(ConditionalExpression node) { return node.Update(Visit(node.Test), Visit(node.IfTrue), Visit(node.IfFalse)); } ////// Visits the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitConstant(ConstantExpression node) { return node; } ////// Visits the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitDebugInfo(DebugInfoExpression node) { return node; } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitDynamic(DynamicExpression node) { Expression[] a = VisitArguments((IArgumentProvider)node); if (a == null) { return node; } return node.Rewrite(a); } ////// Visits the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitDefault(DefaultExpression node) { return node; } ////// Visits the children of the extension expression. /// /// The expression to visit. ///The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. ////// This can be overridden to visit or rewrite specific extension nodes. /// If it is not overridden, this method will call protected internal virtual Expression VisitExtension(Expression node) { return node.VisitChildren(this); } ///, /// which gives the node a chance to walk its children. By default, /// will try to reduce the node. /// /// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitGoto(GotoExpression node) { return node.Update(VisitLabelTarget(node.Target), Visit(node.Value)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitInvocation(InvocationExpression node) { Expression e = Visit(node.Expression); Expression[] a = VisitArguments(node); if (e == node.Expression && a == null) { return node; } return node.Rewrite(e, a); } ////// Visits the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual LabelTarget VisitLabelTarget(LabelTarget node) { return node; } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitLabel(LabelExpression node) { return node.Update(VisitLabelTarget(node.Target), Visit(node.DefaultValue)); } ////// Visits the children of the ///. /// The type of the delegate. /// The expression to visit. ///The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitLambda(Expression node) { return node.Update(Visit(node.Body), VisitAndConvert(node.Parameters, "VisitLambda")); } /// /// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitLoop(LoopExpression node) { return node.Update(VisitLabelTarget(node.BreakLabel), VisitLabelTarget(node.ContinueLabel), Visit(node.Body)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitMember(MemberExpression node) { return node.Update(Visit(node.Expression)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitIndex(IndexExpression node) { Expression o = Visit(node.Object); Expression[] a = VisitArguments(node); if (o == node.Object && a == null) { return node; } return node.Rewrite(o, a); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitMethodCall(MethodCallExpression node) { Expression o = Visit(node.Object); Expression[] a = VisitArguments((IArgumentProvider)node); if (o == node.Object && a == null) { return node; } return node.Rewrite(o, a); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitNewArray(NewArrayExpression node) { return node.Update(Visit(node.Expressions)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] protected internal virtual Expression VisitNew(NewExpression node) { return node.Update(Visit(node.Arguments)); } ////// Visits the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitParameter(ParameterExpression node) { return node; } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitRuntimeVariables(RuntimeVariablesExpression node) { return node.Update(VisitAndConvert(node.Variables, "VisitRuntimeVariables")); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual SwitchCase VisitSwitchCase(SwitchCase node) { return node.Update(Visit(node.TestValues), Visit(node.Body)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitSwitch(SwitchExpression node) { return ValidateSwitch( node, node.Update( Visit(node.SwitchValue), Visit(node.Cases, VisitSwitchCase), Visit(node.DefaultBody) ) ); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual CatchBlock VisitCatchBlock(CatchBlock node) { return node.Update(VisitAndConvert(node.Variable, "VisitCatchBlock"), Visit(node.Filter), Visit(node.Body)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitTry(TryExpression node) { return node.Update( Visit(node.Body), Visit(node.Handlers, VisitCatchBlock), Visit(node.Finally), Visit(node.Fault) ); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitTypeBinary(TypeBinaryExpression node) { return node.Update(Visit(node.Expression)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitUnary(UnaryExpression node) { return ValidateUnary(node, node.Update(Visit(node.Operand))); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitMemberInit(MemberInitExpression node) { return node.Update( VisitAndConvert(node.NewExpression, "VisitMemberInit"), Visit(node.Bindings, VisitMemberBinding) ); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitListInit(ListInitExpression node) { return node.Update( VisitAndConvert(node.NewExpression, "VisitListInit"), Visit(node.Initializers, VisitElementInit) ); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual ElementInit VisitElementInit(ElementInit node) { return node.Update(Visit(node.Arguments)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual MemberBinding VisitMemberBinding(MemberBinding node) { switch (node.BindingType) { case MemberBindingType.Assignment: return VisitMemberAssignment((MemberAssignment)node); case MemberBindingType.MemberBinding: return VisitMemberMemberBinding((MemberMemberBinding)node); case MemberBindingType.ListBinding: return VisitMemberListBinding((MemberListBinding)node); default: throw Error.UnhandledBindingType(node.BindingType); } } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment node) { return node.Update(Visit(node.Expression)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding node) { return node.Update(Visit(node.Bindings, VisitMemberBinding)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding node) { return node.Update(Visit(node.Initializers, VisitElementInit)); } // // Prevent some common cases of invalid rewrites. // // Essentially, we don't want the rewritten node to be semantically // bound by the factory, which may do the wrong thing. Instead we // require derived classes to be explicit about what they want to do if // types change. // private static UnaryExpression ValidateUnary(UnaryExpression before, UnaryExpression after) { if (before != after && before.Method == null) { if (after.Method != null) { throw Error.MustRewriteWithoutMethod(after.Method, "VisitUnary"); } // rethrow has null operand if (before.Operand != null && after.Operand != null) { ValidateChildType(before.Operand.Type, after.Operand.Type, "VisitUnary"); } } return after; } private static BinaryExpression ValidateBinary(BinaryExpression before, BinaryExpression after) { if (before != after && before.Method == null) { if (after.Method != null) { throw Error.MustRewriteWithoutMethod(after.Method, "VisitBinary"); } ValidateChildType(before.Left.Type, after.Left.Type, "VisitBinary"); ValidateChildType(before.Right.Type, after.Right.Type, "VisitBinary"); } return after; } // We wouldn't need this if switch didn't infer the method. private static SwitchExpression ValidateSwitch(SwitchExpression before, SwitchExpression after) { // If we did not have a method, we don't want to bind to one, // it might not be the right thing. if (before.Comparison == null && after.Comparison != null) { throw Error.MustRewriteWithoutMethod(after.Comparison, "VisitSwitch"); } return after; } // Value types must stay as the same type, otherwise it's now a // different operation, e.g. adding two doubles vs adding two ints. private static void ValidateChildType(Type before, Type after, string methodName) { if (before.IsValueType) { if (TypeUtils.AreEquivalent(before, after)) { // types are the same value type return; } } else if (!after.IsValueType) { // both are reference types return; } // Otherwise, it's an invalid type change. throw Error.MustRewriteChildToSameType(before, after, methodName); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. /* **************************************************************************** * * Copyright (c) Microsoft Corporation. * * This source code is subject to terms and conditions of the Microsoft Public License. A * copy of the license can be found in the License.html file at the root of this distribution. If * you cannot locate the Microsoft Public License, please send an email to * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound * by the terms of the Microsoft Public License. * * You must not remove this notice, or any other, from this software. * * * ***************************************************************************/ using System.Collections.ObjectModel; using System.Diagnostics; using System.Dynamic.Utils; using System.Runtime.CompilerServices; #if SILVERLIGHT using System.Core; #endif namespace System.Linq.Expressions { ////// Represents a visitor or rewriter for expression trees. /// ////// This class is designed to be inherited to create more specialized /// classes whose functionality requires traversing, examining or copying /// an expression tree. /// public abstract class ExpressionVisitor { ////// Initializes a new instance of protected ExpressionVisitor() { } ///. /// /// Dispatches the expression to one of the more specialized visit methods in this class. /// /// The expression to visit. ///The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. public virtual Expression Visit(Expression node) { if (node != null) { return node.Accept(this); } return null; } ////// Dispatches the list of expressions to one of the more specialized visit methods in this class. /// /// The expressions to visit. ///The modified expression list, if any of the elements were modified; /// otherwise, returns the original expression list. public ReadOnlyCollectionVisit(ReadOnlyCollection nodes) { Expression[] newNodes = null; for (int i = 0, n = nodes.Count; i < n; i++) { Expression node = Visit(nodes[i]); if (newNodes != null) { newNodes[i] = node; } else if (!object.ReferenceEquals(node, nodes[i])) { newNodes = new Expression[n]; for (int j = 0; j < i; j++) { newNodes[j] = nodes[j]; } newNodes[i] = node; } } if (newNodes == null) { return nodes; } return new TrueReadOnlyCollection (newNodes); } internal Expression[] VisitArguments(IArgumentProvider nodes) { Expression[] newNodes = null; for (int i = 0, n = nodes.ArgumentCount; i < n; i++) { Expression curNode = nodes.GetArgument(i); Expression node = Visit(curNode); if (newNodes != null) { newNodes[i] = node; } else if (!object.ReferenceEquals(node, curNode)) { newNodes = new Expression[n]; for (int j = 0; j < i; j++) { newNodes[j] = nodes.GetArgument(j); } newNodes[i] = node; } } return newNodes; } /// /// Visits all nodes in the collection using a specified element visitor. /// ///The type of the nodes. /// The nodes to visit. /// A delegate that visits a single element, /// optionally replacing it with a new element. ///The modified node list, if any of the elements were modified; /// otherwise, returns the original node list. public static ReadOnlyCollectionVisit (ReadOnlyCollection nodes, Func elementVisitor) { T[] newNodes = null; for (int i = 0, n = nodes.Count; i < n; i++) { T node = elementVisitor(nodes[i]); if (newNodes != null) { newNodes[i] = node; } else if (!object.ReferenceEquals(node, nodes[i])) { newNodes = new T[n]; for (int j = 0; j < i; j++) { newNodes[j] = nodes[j]; } newNodes[i] = node; } } if (newNodes == null) { return nodes; } return new TrueReadOnlyCollection (newNodes); } /// /// Visits an expression, casting the result back to the original expression type. /// ///The type of the expression. /// The expression to visit. /// The name of the calling method; used to report to report a better error message. ///The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. ///The visit method for this node returned a different type. public T VisitAndConvert(T node, string callerName) where T : Expression { if (node == null) { return null; } node = Visit(node) as T; if (node == null) { throw Error.MustRewriteToSameNode(callerName, typeof(T), callerName); } return node; } /// /// Visits an expression, casting the result back to the original expression type. /// ///The type of the expression. /// The expression to visit. /// The name of the calling method; used to report to report a better error message. ///The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. ///The visit method for this node returned a different type. public ReadOnlyCollectionVisitAndConvert (ReadOnlyCollection nodes, string callerName) where T : Expression { T[] newNodes = null; for (int i = 0, n = nodes.Count; i < n; i++) { T node = Visit(nodes[i]) as T; if (node == null) { throw Error.MustRewriteToSameNode(callerName, typeof(T), callerName); } if (newNodes != null) { newNodes[i] = node; } else if (!object.ReferenceEquals(node, nodes[i])) { newNodes = new T[n]; for (int j = 0; j < i; j++) { newNodes[j] = nodes[j]; } newNodes[i] = node; } } if (newNodes == null) { return nodes; } return new TrueReadOnlyCollection (newNodes); } /// /// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitBinary(BinaryExpression node) { // Walk children in evaluation order: left, conversion, right return ValidateBinary( node, node.Update( Visit(node.Left), VisitAndConvert(node.Conversion, "VisitBinary"), Visit(node.Right) ) ); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitBlock(BlockExpression node) { int count = node.ExpressionCount; Expression[] nodes = null; for (int i = 0; i < count; i++) { Expression oldNode = node.GetExpression(i); Expression newNode = Visit(oldNode); if (oldNode != newNode) { if (nodes == null) { nodes = new Expression[count]; } nodes[i] = newNode; } } var v = VisitAndConvert(node.Variables, "VisitBlock"); if (v == node.Variables && nodes == null) { return node; } else { for (int i = 0; i < count; i++) { if (nodes[i] == null) { nodes[i] = node.GetExpression(i); } } } return node.Rewrite(v, nodes); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitConditional(ConditionalExpression node) { return node.Update(Visit(node.Test), Visit(node.IfTrue), Visit(node.IfFalse)); } ////// Visits the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitConstant(ConstantExpression node) { return node; } ////// Visits the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitDebugInfo(DebugInfoExpression node) { return node; } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitDynamic(DynamicExpression node) { Expression[] a = VisitArguments((IArgumentProvider)node); if (a == null) { return node; } return node.Rewrite(a); } ////// Visits the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitDefault(DefaultExpression node) { return node; } ////// Visits the children of the extension expression. /// /// The expression to visit. ///The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. ////// This can be overridden to visit or rewrite specific extension nodes. /// If it is not overridden, this method will call protected internal virtual Expression VisitExtension(Expression node) { return node.VisitChildren(this); } ///, /// which gives the node a chance to walk its children. By default, /// will try to reduce the node. /// /// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitGoto(GotoExpression node) { return node.Update(VisitLabelTarget(node.Target), Visit(node.Value)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitInvocation(InvocationExpression node) { Expression e = Visit(node.Expression); Expression[] a = VisitArguments(node); if (e == node.Expression && a == null) { return node; } return node.Rewrite(e, a); } ////// Visits the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual LabelTarget VisitLabelTarget(LabelTarget node) { return node; } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitLabel(LabelExpression node) { return node.Update(VisitLabelTarget(node.Target), Visit(node.DefaultValue)); } ////// Visits the children of the ///. /// The type of the delegate. /// The expression to visit. ///The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitLambda(Expression node) { return node.Update(Visit(node.Body), VisitAndConvert(node.Parameters, "VisitLambda")); } /// /// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitLoop(LoopExpression node) { return node.Update(VisitLabelTarget(node.BreakLabel), VisitLabelTarget(node.ContinueLabel), Visit(node.Body)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitMember(MemberExpression node) { return node.Update(Visit(node.Expression)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitIndex(IndexExpression node) { Expression o = Visit(node.Object); Expression[] a = VisitArguments(node); if (o == node.Object && a == null) { return node; } return node.Rewrite(o, a); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitMethodCall(MethodCallExpression node) { Expression o = Visit(node.Object); Expression[] a = VisitArguments((IArgumentProvider)node); if (o == node.Object && a == null) { return node; } return node.Rewrite(o, a); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitNewArray(NewArrayExpression node) { return node.Update(Visit(node.Expressions)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] protected internal virtual Expression VisitNew(NewExpression node) { return node.Update(Visit(node.Arguments)); } ////// Visits the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitParameter(ParameterExpression node) { return node; } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitRuntimeVariables(RuntimeVariablesExpression node) { return node.Update(VisitAndConvert(node.Variables, "VisitRuntimeVariables")); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual SwitchCase VisitSwitchCase(SwitchCase node) { return node.Update(Visit(node.TestValues), Visit(node.Body)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitSwitch(SwitchExpression node) { return ValidateSwitch( node, node.Update( Visit(node.SwitchValue), Visit(node.Cases, VisitSwitchCase), Visit(node.DefaultBody) ) ); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual CatchBlock VisitCatchBlock(CatchBlock node) { return node.Update(VisitAndConvert(node.Variable, "VisitCatchBlock"), Visit(node.Filter), Visit(node.Body)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitTry(TryExpression node) { return node.Update( Visit(node.Body), Visit(node.Handlers, VisitCatchBlock), Visit(node.Finally), Visit(node.Fault) ); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitTypeBinary(TypeBinaryExpression node) { return node.Update(Visit(node.Expression)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitUnary(UnaryExpression node) { return ValidateUnary(node, node.Update(Visit(node.Operand))); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitMemberInit(MemberInitExpression node) { return node.Update( VisitAndConvert(node.NewExpression, "VisitMemberInit"), Visit(node.Bindings, VisitMemberBinding) ); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected internal virtual Expression VisitListInit(ListInitExpression node) { return node.Update( VisitAndConvert(node.NewExpression, "VisitListInit"), Visit(node.Initializers, VisitElementInit) ); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual ElementInit VisitElementInit(ElementInit node) { return node.Update(Visit(node.Arguments)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual MemberBinding VisitMemberBinding(MemberBinding node) { switch (node.BindingType) { case MemberBindingType.Assignment: return VisitMemberAssignment((MemberAssignment)node); case MemberBindingType.MemberBinding: return VisitMemberMemberBinding((MemberMemberBinding)node); case MemberBindingType.ListBinding: return VisitMemberListBinding((MemberListBinding)node); default: throw Error.UnhandledBindingType(node.BindingType); } } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment node) { return node.Update(Visit(node.Expression)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding node) { return node.Update(Visit(node.Bindings, VisitMemberBinding)); } ////// Visits the children of the /// The expression to visit. ///. /// The modified expression, if it or any subexpression was modified; /// otherwise, returns the original expression. protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding node) { return node.Update(Visit(node.Initializers, VisitElementInit)); } // // Prevent some common cases of invalid rewrites. // // Essentially, we don't want the rewritten node to be semantically // bound by the factory, which may do the wrong thing. Instead we // require derived classes to be explicit about what they want to do if // types change. // private static UnaryExpression ValidateUnary(UnaryExpression before, UnaryExpression after) { if (before != after && before.Method == null) { if (after.Method != null) { throw Error.MustRewriteWithoutMethod(after.Method, "VisitUnary"); } // rethrow has null operand if (before.Operand != null && after.Operand != null) { ValidateChildType(before.Operand.Type, after.Operand.Type, "VisitUnary"); } } return after; } private static BinaryExpression ValidateBinary(BinaryExpression before, BinaryExpression after) { if (before != after && before.Method == null) { if (after.Method != null) { throw Error.MustRewriteWithoutMethod(after.Method, "VisitBinary"); } ValidateChildType(before.Left.Type, after.Left.Type, "VisitBinary"); ValidateChildType(before.Right.Type, after.Right.Type, "VisitBinary"); } return after; } // We wouldn't need this if switch didn't infer the method. private static SwitchExpression ValidateSwitch(SwitchExpression before, SwitchExpression after) { // If we did not have a method, we don't want to bind to one, // it might not be the right thing. if (before.Comparison == null && after.Comparison != null) { throw Error.MustRewriteWithoutMethod(after.Comparison, "VisitSwitch"); } return after; } // Value types must stay as the same type, otherwise it's now a // different operation, e.g. adding two doubles vs adding two ints. private static void ValidateChildType(Type before, Type after, string methodName) { if (before.IsValueType) { if (TypeUtils.AreEquivalent(before, after)) { // types are the same value type return; } } else if (!after.IsValueType) { // both are reference types return; } // Otherwise, it's an invalid type change. throw Error.MustRewriteChildToSameType(before, after, methodName); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- AssertFilter.cs
- WebPartCatalogAddVerb.cs
- DeviceContext2.cs
- Rect.cs
- Vector3DCollectionValueSerializer.cs
- prompt.cs
- ObjectPersistData.cs
- BamlResourceDeserializer.cs
- WorkflowServiceHostFactory.cs
- Crypto.cs
- BaseCodeDomTreeGenerator.cs
- CommonDialog.cs
- EntityContainerEntitySet.cs
- HostedNamedPipeTransportManager.cs
- ComboBoxAutomationPeer.cs
- ResourceAssociationSet.cs
- ResolveNameEventArgs.cs
- BindingExpressionBase.cs
- X509ServiceCertificateAuthentication.cs
- PageAdapter.cs
- EntityDataReader.cs
- NameTable.cs
- TransactionManager.cs
- TimelineClockCollection.cs
- HotCommands.cs
- ModelItemCollection.cs
- XPathNodeList.cs
- ExponentialEase.cs
- SpotLight.cs
- BindingCollection.cs
- LambdaCompiler.Address.cs
- ThreadPool.cs
- WebErrorHandler.cs
- DataList.cs
- RawStylusInput.cs
- initElementDictionary.cs
- ComplexPropertyEntry.cs
- TextServicesManager.cs
- ByteAnimation.cs
- NativeWindow.cs
- SystemTcpStatistics.cs
- ReflectionUtil.cs
- DataTemplateKey.cs
- XmlSerializationWriter.cs
- OpCopier.cs
- oledbconnectionstring.cs
- VirtualPathExtension.cs
- PrivilegeNotHeldException.cs
- SymbolDocumentGenerator.cs
- AssemblyHash.cs
- GradientStop.cs
- DataBinding.cs
- milexports.cs
- CurrentChangedEventManager.cs
- ControlCachePolicy.cs
- AddInEnvironment.cs
- ClosableStream.cs
- DataGridViewColumnCollectionEditor.cs
- XmlLoader.cs
- SevenBitStream.cs
- TextBoxBase.cs
- XPathChildIterator.cs
- SamlAuthorityBinding.cs
- XsdCachingReader.cs
- XPathBuilder.cs
- FixedHyperLink.cs
- PlainXmlWriter.cs
- JoinElimination.cs
- Currency.cs
- DataGridViewLinkCell.cs
- GlyphInfoList.cs
- ViewBox.cs
- AttachedPropertyMethodSelector.cs
- MarshalByRefObject.cs
- DriveNotFoundException.cs
- Label.cs
- TimeZoneInfo.cs
- SettingsPropertyNotFoundException.cs
- TextBounds.cs
- ItemDragEvent.cs
- ActivityContext.cs
- BamlRecordReader.cs
- Propagator.JoinPropagator.JoinPredicateVisitor.cs
- LineVisual.cs
- ObservableCollection.cs
- DataControlFieldCell.cs
- XmlDocumentSchema.cs
- SpotLight.cs
- XmlStringTable.cs
- GenericXmlSecurityToken.cs
- SecurityDocument.cs
- X509ClientCertificateAuthentication.cs
- XamlPoint3DCollectionSerializer.cs
- HMACSHA1.cs
- ImageUrlEditor.cs
- XslAst.cs
- MappingMetadataHelper.cs
- RemotingConfigParser.cs
- ValidationSummary.cs
- WS2007FederationHttpBindingCollectionElement.cs