Code:
/ 4.0 / 4.0 / untmp / 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.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- FunctionDescription.cs
- DataGridViewCellValueEventArgs.cs
- DBPropSet.cs
- ProtocolViolationException.cs
- BinaryOperationBinder.cs
- Compiler.cs
- ToolboxCategory.cs
- CacheSection.cs
- DbProviderSpecificTypePropertyAttribute.cs
- LingerOption.cs
- SqlXml.cs
- EmptyStringExpandableObjectConverter.cs
- NamedPipeTransportSecurity.cs
- UITypeEditor.cs
- ColorConvertedBitmapExtension.cs
- AsymmetricSignatureDeformatter.cs
- sitestring.cs
- XmlSchemaObject.cs
- X509SecurityTokenAuthenticator.cs
- DataGridViewRowPostPaintEventArgs.cs
- ManagedCodeMarkers.cs
- XmlSchemaExternal.cs
- CellParagraph.cs
- Keywords.cs
- DynamicMethod.cs
- PublisherIdentityPermission.cs
- Dump.cs
- TextDecorationCollectionConverter.cs
- PrintDialogException.cs
- VisualProxy.cs
- FrameworkElementFactoryMarkupObject.cs
- LineProperties.cs
- Ticks.cs
- DesignSurfaceManager.cs
- KeyboardEventArgs.cs
- CookieParameter.cs
- AutomationFocusChangedEventArgs.cs
- UInt16Storage.cs
- ListenerElementsCollection.cs
- EdmMember.cs
- PermissionToken.cs
- DiscoveryDocumentSearchPattern.cs
- KeyConverter.cs
- FragmentQueryKB.cs
- ShaderEffect.cs
- XmlSchemaAnnotated.cs
- EditCommandColumn.cs
- MsmqBindingElementBase.cs
- HtmlControl.cs
- ProfileGroupSettingsCollection.cs
- DataContractSerializerOperationFormatter.cs
- TracePayload.cs
- TextTreeExtractElementUndoUnit.cs
- TextBox.cs
- TextElementCollectionHelper.cs
- TransformedBitmap.cs
- X509Chain.cs
- Graphics.cs
- TextSpanModifier.cs
- XmlSchemaDatatype.cs
- WebPartEventArgs.cs
- DataGridViewCellParsingEventArgs.cs
- WebPartCloseVerb.cs
- VisualStyleRenderer.cs
- Avt.cs
- serverconfig.cs
- GenericTextProperties.cs
- StringExpressionSet.cs
- StagingAreaInputItem.cs
- SplineKeyFrames.cs
- EncodingTable.cs
- TextViewDesigner.cs
- PageCache.cs
- PopupEventArgs.cs
- TimeSpanMinutesConverter.cs
- DataFormats.cs
- CompletionBookmark.cs
- WindowExtensionMethods.cs
- ClientBuildManager.cs
- EventLogPropertySelector.cs
- ListViewUpdateEventArgs.cs
- SafeNativeMethods.cs
- MessageSmuggler.cs
- AmbiguousMatchException.cs
- IProvider.cs
- TableCell.cs
- DataGridViewRowPostPaintEventArgs.cs
- AnimationStorage.cs
- SoapEnumAttribute.cs
- EventDescriptor.cs
- newinstructionaction.cs
- NativeMethods.cs
- OrderedDictionary.cs
- Configuration.cs
- TypeSystem.cs
- ToolStripPanelRenderEventArgs.cs
- List.cs
- BindingExpressionBase.cs
- DataObjectMethodAttribute.cs
- XmlChildNodes.cs