Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Compiler / ExpressionQuoter.cs / 1305376 / ExpressionQuoter.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.Generic; using System.ComponentModel; using System.Diagnostics; using System.Dynamic.Utils; using System.Linq.Expressions; using System.Linq.Expressions.Compiler; namespace System.Runtime.CompilerServices { public partial class RuntimeOps { ////// Quotes the provided expression tree. /// /// The expression to quote. /// The hoisted local state provided by the compiler. /// The actual hoisted local values. ///The quoted expression. [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)] public static Expression Quote(Expression expression, object hoistedLocals, object[] locals) { Debug.Assert(hoistedLocals != null && locals != null); var quoter = new ExpressionQuoter((HoistedLocals)hoistedLocals, locals); return quoter.Visit(expression); } ////// Combines two runtime variable lists and returns a new list. /// /// The first list. /// The second list. /// The index array indicating which list to get variables from. ///The merged runtime variables. [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)] public static IRuntimeVariables MergeRuntimeVariables(IRuntimeVariables first, IRuntimeVariables second, int[] indexes) { return new MergedRuntimeVariables(first, second, indexes); } // Modifies a quoted Expression instance by changing hoisted variables and // parameters into hoisted local references. The variable's StrongBox is // burned as a constant, and all hoisted variables/parameters are rewritten // as indexing expressions. // // The behavior of Quote is indended to be like C# and VB expression quoting private sealed class ExpressionQuoter : ExpressionVisitor { private readonly HoistedLocals _scope; private readonly object[] _locals; // A stack of variables that are defined in nested scopes. We search // this first when resolving a variable in case a nested scope shadows // one of our variable instances. private readonly Stack> _shadowedVars = new Stack >(); internal ExpressionQuoter(HoistedLocals scope, object[] locals) { _scope = scope; _locals = locals; } protected internal override Expression VisitLambda (Expression node) { _shadowedVars.Push(new Set (node.Parameters)); Expression b = Visit(node.Body); _shadowedVars.Pop(); if (b == node.Body) { return node; } return Expression.Lambda (b, node.Name, node.TailCall, node.Parameters); } protected internal override Expression VisitBlock(BlockExpression node) { if (node.Variables.Count > 0) { _shadowedVars.Push(new Set (node.Variables)); } var b = Visit(node.Expressions); if (node.Variables.Count > 0) { _shadowedVars.Pop(); } if (b == node.Expressions) { return node; } return Expression.Block(node.Variables, b); } protected override CatchBlock VisitCatchBlock(CatchBlock node) { if (node.Variable != null) { _shadowedVars.Push(new Set (new[] { node.Variable })); } Expression b = Visit(node.Body); Expression f = Visit(node.Filter); if (node.Variable != null) { _shadowedVars.Pop(); } if (b == node.Body && f == node.Filter) { return node; } return Expression.MakeCatchBlock(node.Test, node.Variable, b, f); } protected internal override Expression VisitRuntimeVariables(RuntimeVariablesExpression node) { int count = node.Variables.Count; var boxes = new List (); var vars = new List (); var indexes = new int[count]; for (int i = 0; i < count; i++) { IStrongBox box = GetBox(node.Variables[i]); if (box == null) { indexes[i] = vars.Count; vars.Add(node.Variables[i]); } else { indexes[i] = -1 - boxes.Count; boxes.Add(box); } } // No variables were rewritten. Just return the original node if (boxes.Count == 0) { return node; } var boxesConst = Expression.Constant(new RuntimeVariables(boxes.ToArray()), typeof(IRuntimeVariables)); // All of them were rewritten. Just return the array as a constant if (vars.Count == 0) { return boxesConst; } // Otherwise, we need to return an object that merges them return Expression.Call( typeof(RuntimeOps).GetMethod("MergeRuntimeVariables"), Expression.RuntimeVariables(new TrueReadOnlyCollection (vars.ToArray())), boxesConst, Expression.Constant(indexes) ); } protected internal override Expression VisitParameter(ParameterExpression node) { IStrongBox box = GetBox(node); if (box == null) { return node; } return Expression.Field(Expression.Constant(box), "Value"); } private IStrongBox GetBox(ParameterExpression variable) { // Skip variables that are shadowed by a nested scope/lambda foreach (Set hidden in _shadowedVars) { if (hidden.Contains(variable)) { return null; } } HoistedLocals scope = _scope; object[] locals = _locals; while (true) { int hoistIndex; if (scope.Indexes.TryGetValue(variable, out hoistIndex)) { return (IStrongBox)locals[hoistIndex]; } scope = scope.Parent; if (scope == null) { break; } locals = HoistedLocals.GetParent(locals); } // Unbound variable: an error should've been thrown already // from VariableBinder throw ContractUtils.Unreachable; } } private sealed class RuntimeVariables : IRuntimeVariables { private readonly IStrongBox[] _boxes; internal RuntimeVariables(IStrongBox[] boxes) { _boxes = boxes; } int IRuntimeVariables.Count { get { return _boxes.Length; } } object IRuntimeVariables.this[int index] { get { return _boxes[index].Value; } set { _boxes[index].Value = value; } } } /// /// Provides a list of variables, supporing read/write of the values /// Exposed via RuntimeVariablesExpression /// private sealed class MergedRuntimeVariables : IRuntimeVariables { private readonly IRuntimeVariables _first; private readonly IRuntimeVariables _second; // For reach item, the index into the first or second list // Positive values mean the first array, negative means the second private readonly int[] _indexes; internal MergedRuntimeVariables(IRuntimeVariables first, IRuntimeVariables second, int[] indexes) { _first = first; _second = second; _indexes = indexes; } public int Count { get { return _indexes.Length; } } public object this[int index] { get { index = _indexes[index]; return (index >= 0) ? _first[index] : _second[-1 - index]; } set { index = _indexes[index]; if (index >= 0) { _first[index] = value; } else { _second[-1 - index] = value; } } } } } } // 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.Generic; using System.ComponentModel; using System.Diagnostics; using System.Dynamic.Utils; using System.Linq.Expressions; using System.Linq.Expressions.Compiler; namespace System.Runtime.CompilerServices { public partial class RuntimeOps { ////// Quotes the provided expression tree. /// /// The expression to quote. /// The hoisted local state provided by the compiler. /// The actual hoisted local values. ///The quoted expression. [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)] public static Expression Quote(Expression expression, object hoistedLocals, object[] locals) { Debug.Assert(hoistedLocals != null && locals != null); var quoter = new ExpressionQuoter((HoistedLocals)hoistedLocals, locals); return quoter.Visit(expression); } ////// Combines two runtime variable lists and returns a new list. /// /// The first list. /// The second list. /// The index array indicating which list to get variables from. ///The merged runtime variables. [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)] public static IRuntimeVariables MergeRuntimeVariables(IRuntimeVariables first, IRuntimeVariables second, int[] indexes) { return new MergedRuntimeVariables(first, second, indexes); } // Modifies a quoted Expression instance by changing hoisted variables and // parameters into hoisted local references. The variable's StrongBox is // burned as a constant, and all hoisted variables/parameters are rewritten // as indexing expressions. // // The behavior of Quote is indended to be like C# and VB expression quoting private sealed class ExpressionQuoter : ExpressionVisitor { private readonly HoistedLocals _scope; private readonly object[] _locals; // A stack of variables that are defined in nested scopes. We search // this first when resolving a variable in case a nested scope shadows // one of our variable instances. private readonly Stack> _shadowedVars = new Stack >(); internal ExpressionQuoter(HoistedLocals scope, object[] locals) { _scope = scope; _locals = locals; } protected internal override Expression VisitLambda (Expression node) { _shadowedVars.Push(new Set (node.Parameters)); Expression b = Visit(node.Body); _shadowedVars.Pop(); if (b == node.Body) { return node; } return Expression.Lambda (b, node.Name, node.TailCall, node.Parameters); } protected internal override Expression VisitBlock(BlockExpression node) { if (node.Variables.Count > 0) { _shadowedVars.Push(new Set (node.Variables)); } var b = Visit(node.Expressions); if (node.Variables.Count > 0) { _shadowedVars.Pop(); } if (b == node.Expressions) { return node; } return Expression.Block(node.Variables, b); } protected override CatchBlock VisitCatchBlock(CatchBlock node) { if (node.Variable != null) { _shadowedVars.Push(new Set (new[] { node.Variable })); } Expression b = Visit(node.Body); Expression f = Visit(node.Filter); if (node.Variable != null) { _shadowedVars.Pop(); } if (b == node.Body && f == node.Filter) { return node; } return Expression.MakeCatchBlock(node.Test, node.Variable, b, f); } protected internal override Expression VisitRuntimeVariables(RuntimeVariablesExpression node) { int count = node.Variables.Count; var boxes = new List (); var vars = new List (); var indexes = new int[count]; for (int i = 0; i < count; i++) { IStrongBox box = GetBox(node.Variables[i]); if (box == null) { indexes[i] = vars.Count; vars.Add(node.Variables[i]); } else { indexes[i] = -1 - boxes.Count; boxes.Add(box); } } // No variables were rewritten. Just return the original node if (boxes.Count == 0) { return node; } var boxesConst = Expression.Constant(new RuntimeVariables(boxes.ToArray()), typeof(IRuntimeVariables)); // All of them were rewritten. Just return the array as a constant if (vars.Count == 0) { return boxesConst; } // Otherwise, we need to return an object that merges them return Expression.Call( typeof(RuntimeOps).GetMethod("MergeRuntimeVariables"), Expression.RuntimeVariables(new TrueReadOnlyCollection (vars.ToArray())), boxesConst, Expression.Constant(indexes) ); } protected internal override Expression VisitParameter(ParameterExpression node) { IStrongBox box = GetBox(node); if (box == null) { return node; } return Expression.Field(Expression.Constant(box), "Value"); } private IStrongBox GetBox(ParameterExpression variable) { // Skip variables that are shadowed by a nested scope/lambda foreach (Set hidden in _shadowedVars) { if (hidden.Contains(variable)) { return null; } } HoistedLocals scope = _scope; object[] locals = _locals; while (true) { int hoistIndex; if (scope.Indexes.TryGetValue(variable, out hoistIndex)) { return (IStrongBox)locals[hoistIndex]; } scope = scope.Parent; if (scope == null) { break; } locals = HoistedLocals.GetParent(locals); } // Unbound variable: an error should've been thrown already // from VariableBinder throw ContractUtils.Unreachable; } } private sealed class RuntimeVariables : IRuntimeVariables { private readonly IStrongBox[] _boxes; internal RuntimeVariables(IStrongBox[] boxes) { _boxes = boxes; } int IRuntimeVariables.Count { get { return _boxes.Length; } } object IRuntimeVariables.this[int index] { get { return _boxes[index].Value; } set { _boxes[index].Value = value; } } } /// /// Provides a list of variables, supporing read/write of the values /// Exposed via RuntimeVariablesExpression /// private sealed class MergedRuntimeVariables : IRuntimeVariables { private readonly IRuntimeVariables _first; private readonly IRuntimeVariables _second; // For reach item, the index into the first or second list // Positive values mean the first array, negative means the second private readonly int[] _indexes; internal MergedRuntimeVariables(IRuntimeVariables first, IRuntimeVariables second, int[] indexes) { _first = first; _second = second; _indexes = indexes; } public int Count { get { return _indexes.Length; } } public object this[int index] { get { index = _indexes[index]; return (index >= 0) ? _first[index] : _second[-1 - index]; } set { index = _indexes[index]; if (index >= 0) { _first[index] = value; } else { _second[-1 - index] = value; } } } } } } // 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
- ComboBox.cs
- FixedTextPointer.cs
- HealthMonitoringSectionHelper.cs
- COM2ComponentEditor.cs
- Pens.cs
- StyleCollection.cs
- PeerTransportCredentialType.cs
- EntityDesignerDataSourceView.cs
- ScrollEvent.cs
- ToolStripGripRenderEventArgs.cs
- HTMLTextWriter.cs
- MenuStrip.cs
- JsonFaultDetail.cs
- Vector3DValueSerializer.cs
- IResourceProvider.cs
- OracleColumn.cs
- RequestBringIntoViewEventArgs.cs
- TextWriterTraceListener.cs
- PermissionSet.cs
- GridViewDeletedEventArgs.cs
- ModulesEntry.cs
- ToolboxCategory.cs
- ControlAdapter.cs
- lengthconverter.cs
- WebPartCatalogCloseVerb.cs
- FontWeights.cs
- CultureTableRecord.cs
- CreateUserWizard.cs
- MeasureItemEvent.cs
- HeaderUtility.cs
- DateTimePicker.cs
- DbConnectionOptions.cs
- Material.cs
- IdentityNotMappedException.cs
- InkCanvasFeedbackAdorner.cs
- ResourcesChangeInfo.cs
- CollectionBase.cs
- DataGridViewCellPaintingEventArgs.cs
- TransactionContextManager.cs
- BitmapScalingModeValidation.cs
- SafeNativeMethodsOther.cs
- VirtualPathProvider.cs
- PreviewControlDesigner.cs
- ExceptionUtil.cs
- SystemWebSectionGroup.cs
- LogSwitch.cs
- FeatureSupport.cs
- WebHostedComPlusServiceHost.cs
- DrawingContextDrawingContextWalker.cs
- SqlDependency.cs
- RoutedEventConverter.cs
- Keyboard.cs
- NavigationPropertyEmitter.cs
- BuildProviderAppliesToAttribute.cs
- DataStreams.cs
- WebPartConnectionsDisconnectVerb.cs
- ReadWriteSpinLock.cs
- SerialPinChanges.cs
- XPathNodeInfoAtom.cs
- TreeView.cs
- DataFormats.cs
- SqlUDTStorage.cs
- UnaryExpressionHelper.cs
- MenuItemStyleCollectionEditor.cs
- OracleFactory.cs
- SmtpMail.cs
- StringExpressionSet.cs
- Preprocessor.cs
- ResourceExpression.cs
- EntityClientCacheKey.cs
- FontFamily.cs
- ToolStripContentPanel.cs
- HashCryptoHandle.cs
- DeferredTextReference.cs
- DetailsViewInsertEventArgs.cs
- Comparer.cs
- InputLangChangeRequestEvent.cs
- ExceptionUtil.cs
- ObjRef.cs
- RuntimeResourceSet.cs
- AutomationPropertyChangedEventArgs.cs
- AnnotationComponentChooser.cs
- odbcmetadatafactory.cs
- ResourcesGenerator.cs
- VersionedStreamOwner.cs
- MultiSelectRootGridEntry.cs
- DiscoveryClientProtocol.cs
- EditorAttributeInfo.cs
- DataServiceQuery.cs
- DtrList.cs
- GPRECT.cs
- WindowsHyperlink.cs
- XmlExtensionFunction.cs
- PropertyChangedEventManager.cs
- XmlLinkedNode.cs
- AssociationType.cs
- SchemaName.cs
- ToggleButtonAutomationPeer.cs
- PropertyConverter.cs
- ProfilePropertyNameValidator.cs