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
- RelationshipWrapper.cs
- DataGridViewCheckBoxColumn.cs
- XmlObjectSerializerReadContextComplex.cs
- CacheDict.cs
- GridViewRowCollection.cs
- ProfileProvider.cs
- PropertyIDSet.cs
- TraceInternal.cs
- LinqDataSourceView.cs
- InvokeMethodActivity.cs
- DocumentCollection.cs
- MatrixAnimationBase.cs
- TemplateBuilder.cs
- PageWrapper.cs
- LinkUtilities.cs
- SQLInt32Storage.cs
- AmbientLight.cs
- ContainerVisual.cs
- ColorContextHelper.cs
- DataGridViewRowPrePaintEventArgs.cs
- COM2ColorConverter.cs
- Stylesheet.cs
- OletxTransactionManager.cs
- MsmqBindingMonitor.cs
- ListenerElementsCollection.cs
- IndependentlyAnimatedPropertyMetadata.cs
- ReachPageContentSerializerAsync.cs
- UriWriter.cs
- ConfigurationPropertyAttribute.cs
- ParallelTimeline.cs
- handlecollector.cs
- XPathMultyIterator.cs
- Menu.cs
- TreeBuilder.cs
- SplineKeyFrames.cs
- FreezableDefaultValueFactory.cs
- BufferedStream.cs
- DocumentCollection.cs
- MultiBinding.cs
- IgnorePropertiesAttribute.cs
- Deflater.cs
- AttributeUsageAttribute.cs
- ValidatingPropertiesEventArgs.cs
- TraceHwndHost.cs
- SessionEndingEventArgs.cs
- XmlWellformedWriter.cs
- ElementHost.cs
- MissingMemberException.cs
- HitTestWithGeometryDrawingContextWalker.cs
- NameTable.cs
- DataContext.cs
- ExpandableObjectConverter.cs
- AgileSafeNativeMemoryHandle.cs
- TCEAdapterGenerator.cs
- ToolStripPanelCell.cs
- RotateTransform3D.cs
- Privilege.cs
- WrappedDispatcherException.cs
- TargetConverter.cs
- CollectionViewGroup.cs
- SiblingIterators.cs
- SmiTypedGetterSetter.cs
- TextTreeObjectNode.cs
- ObjectListShowCommandsEventArgs.cs
- FrameworkRichTextComposition.cs
- DebugHandleTracker.cs
- baseaxisquery.cs
- Block.cs
- MachineKeySection.cs
- Main.cs
- Config.cs
- DataBoundControlActionList.cs
- ProxySimple.cs
- ObjectDataSourceView.cs
- ListDictionaryInternal.cs
- ListItemConverter.cs
- DataGridAddNewRow.cs
- SerializationStore.cs
- ImportContext.cs
- CollectionConverter.cs
- ObjectCache.cs
- ThaiBuddhistCalendar.cs
- SecurityContext.cs
- DBParameter.cs
- HandleCollector.cs
- XPathDocumentNavigator.cs
- ProtocolViolationException.cs
- UITypeEditor.cs
- RuntimeEnvironment.cs
- URIFormatException.cs
- PersonalizationDictionary.cs
- PixelFormatConverter.cs
- XmlParser.cs
- PermissionListSet.cs
- RegexCompiler.cs
- EnumConverter.cs
- TextView.cs
- cryptoapiTransform.cs
- Char.cs
- HTMLTextWriter.cs