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
- SessionPageStateSection.cs
- PlatformNotSupportedException.cs
- StringArrayEditor.cs
- COM2IPerPropertyBrowsingHandler.cs
- EventArgs.cs
- StylusButtonCollection.cs
- ListViewItemEventArgs.cs
- VirtualizedCellInfoCollection.cs
- WindowsNonControl.cs
- IndicCharClassifier.cs
- Decoder.cs
- DiagnosticsConfigurationHandler.cs
- UrlAuthorizationModule.cs
- XmlCharType.cs
- Vector3DAnimationBase.cs
- Rotation3DAnimationUsingKeyFrames.cs
- WebUtil.cs
- ConfigXmlWhitespace.cs
- RemoteWebConfigurationHost.cs
- CompositeFontFamily.cs
- DataGridCell.cs
- PropertyMappingExceptionEventArgs.cs
- _Events.cs
- RegexBoyerMoore.cs
- PackWebRequestFactory.cs
- ConfigurationPropertyCollection.cs
- PtsHelper.cs
- ResXBuildProvider.cs
- Vector3dCollection.cs
- TreeNodeBinding.cs
- CodePropertyReferenceExpression.cs
- EdgeModeValidation.cs
- Transform.cs
- NetworkInterface.cs
- Triplet.cs
- PrintDialogException.cs
- Claim.cs
- DesignerRegion.cs
- RightsManagementEncryptedStream.cs
- ClientOperation.cs
- storepermission.cs
- DataSourceView.cs
- ControlValuePropertyAttribute.cs
- GPPOINT.cs
- TimeZone.cs
- HttpBrowserCapabilitiesBase.cs
- TextTrailingCharacterEllipsis.cs
- RuntimeHandles.cs
- DocumentPageTextView.cs
- WinEventTracker.cs
- PointCollectionConverter.cs
- CodeDirectionExpression.cs
- Material.cs
- CssClassPropertyAttribute.cs
- CodeIndexerExpression.cs
- XmlToDatasetMap.cs
- EditorResources.cs
- CodeRegionDirective.cs
- MouseButton.cs
- XmlMemberMapping.cs
- ProfilePropertyNameValidator.cs
- CodeSnippetTypeMember.cs
- SmiGettersStream.cs
- DragEventArgs.cs
- AppSettingsReader.cs
- FontWeightConverter.cs
- StylusPointCollection.cs
- StatusBarPanelClickEvent.cs
- File.cs
- JsonWriterDelegator.cs
- RawStylusInput.cs
- XmlElementAttribute.cs
- WindowsComboBox.cs
- _CommandStream.cs
- EntityDataSourceEntitySetNameItem.cs
- ExtensionSurface.cs
- DecoderFallback.cs
- ProcessHost.cs
- ServiceContractGenerationContext.cs
- ListViewSortEventArgs.cs
- FormClosedEvent.cs
- BindingBase.cs
- CodeIndexerExpression.cs
- CompiledXpathExpr.cs
- QilCloneVisitor.cs
- IpcChannelHelper.cs
- ExpressionBindingCollection.cs
- ReturnValue.cs
- RC2CryptoServiceProvider.cs
- PolyBezierSegmentFigureLogic.cs
- DataListItemEventArgs.cs
- MSAAEventDispatcher.cs
- StatusBarPanel.cs
- AnnotationObservableCollection.cs
- SqlDependency.cs
- CodeAccessSecurityEngine.cs
- ImpersonateTokenRef.cs
- RelationalExpressions.cs
- ServiceDescriptions.cs
- TaskDesigner.cs