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
- TrackingProfileSerializer.cs
- CSharpCodeProvider.cs
- MembershipValidatePasswordEventArgs.cs
- TCPListener.cs
- FaultHandlingFilter.cs
- XAMLParseException.cs
- SqlVisitor.cs
- DialogResultConverter.cs
- IntSecurity.cs
- FileFormatException.cs
- PenLineCapValidation.cs
- SymLanguageVendor.cs
- PathSegment.cs
- HitTestParameters3D.cs
- DataGridViewButtonCell.cs
- ByteStreamGeometryContext.cs
- InvalidWMPVersionException.cs
- DataGridViewRowEventArgs.cs
- RangeValueProviderWrapper.cs
- GradientStop.cs
- GetPageCompletedEventArgs.cs
- PeerObject.cs
- DynamicValueConverter.cs
- Bits.cs
- DeploymentSectionCache.cs
- EmptyImpersonationContext.cs
- URL.cs
- ExpandedWrapper.cs
- Aggregates.cs
- ClientFormsIdentity.cs
- ChineseLunisolarCalendar.cs
- XmlBufferReader.cs
- SafeEventLogWriteHandle.cs
- StorageModelBuildProvider.cs
- SpinLock.cs
- IPipelineRuntime.cs
- Types.cs
- autovalidator.cs
- XmlSignatureManifest.cs
- PriorityBinding.cs
- PTUtility.cs
- JournalNavigationScope.cs
- CapabilitiesUse.cs
- DefaultAssemblyResolver.cs
- HitTestParameters.cs
- ProfilePropertySettingsCollection.cs
- ButtonStandardAdapter.cs
- EndpointFilterProvider.cs
- ApplicationContext.cs
- CodeArrayIndexerExpression.cs
- SnapshotChangeTrackingStrategy.cs
- dtdvalidator.cs
- DesignerExtenders.cs
- CompressionTracing.cs
- MasterPageParser.cs
- NameScope.cs
- XmlLangPropertyAttribute.cs
- AnnotationResourceChangedEventArgs.cs
- wgx_render.cs
- Span.cs
- GroupBoxRenderer.cs
- Helper.cs
- WindowsProgressbar.cs
- TreeBuilder.cs
- LambdaSerializationException.cs
- DetailsViewInsertedEventArgs.cs
- Int16AnimationUsingKeyFrames.cs
- AdjustableArrowCap.cs
- MD5HashHelper.cs
- MethodAccessException.cs
- ReflectionUtil.cs
- InfoCardCryptoHelper.cs
- SelectedDatesCollection.cs
- FullTextLine.cs
- XamlBrushSerializer.cs
- EmptyReadOnlyDictionaryInternal.cs
- ObjectItemAssemblyLoader.cs
- XsdCachingReader.cs
- InputScopeNameConverter.cs
- BaseTreeIterator.cs
- OdbcRowUpdatingEvent.cs
- ChildDocumentBlock.cs
- ViewValidator.cs
- MexTcpBindingElement.cs
- JsonGlobals.cs
- OleDbCommand.cs
- XmlAttributeCollection.cs
- ProjectionCamera.cs
- LinqToSqlWrapper.cs
- InputLanguageManager.cs
- CategoryNameCollection.cs
- RegisteredArrayDeclaration.cs
- X500Name.cs
- UmAlQuraCalendar.cs
- PagerSettings.cs
- SchemaNames.cs
- PolicyConversionContext.cs
- DynamicDiscoveryDocument.cs
- DocumentViewerBase.cs
- ClientFormsAuthenticationMembershipProvider.cs