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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- StrongNameKeyPair.cs
- TextTreeUndoUnit.cs
- ConfigurationStrings.cs
- DataBoundControlHelper.cs
- MethodCallConverter.cs
- ScriptManagerProxy.cs
- FilterEventArgs.cs
- MimePart.cs
- ControlPropertyNameConverter.cs
- DataGrid.cs
- Stroke.cs
- LocalizationCodeDomSerializer.cs
- __Error.cs
- DesignerActionMethodItem.cs
- DecoratedNameAttribute.cs
- PeerTransportBindingElement.cs
- XmlDataCollection.cs
- EntityKeyElement.cs
- OutputCacheProfile.cs
- ActivationProxy.cs
- DropDownHolder.cs
- FunctionUpdateCommand.cs
- Constant.cs
- ScrollChrome.cs
- AtlasWeb.Designer.cs
- prompt.cs
- LocationSectionRecord.cs
- JavaScriptObjectDeserializer.cs
- HttpStreamMessageEncoderFactory.cs
- TraceContextEventArgs.cs
- Html32TextWriter.cs
- FixedDSBuilder.cs
- AssemblyUtil.cs
- LazyTextWriterCreator.cs
- SignerInfo.cs
- PluralizationService.cs
- ErrorStyle.cs
- DynamicActivity.cs
- PkcsMisc.cs
- DateTimeFormatInfo.cs
- ComNativeDescriptor.cs
- BatchParser.cs
- ColorConverter.cs
- Internal.cs
- Renderer.cs
- InternalResources.cs
- PopupRoot.cs
- AttachedAnnotationChangedEventArgs.cs
- Expression.DebuggerProxy.cs
- MonthCalendar.cs
- EventListener.cs
- ConnectionInterfaceCollection.cs
- BindingNavigator.cs
- ByteKeyFrameCollection.cs
- _DomainName.cs
- Stream.cs
- ImportedNamespaceContextItem.cs
- CompositeControl.cs
- ImageAnimator.cs
- RuntimeVariablesExpression.cs
- RealProxy.cs
- ScrollViewer.cs
- MarshalDirectiveException.cs
- WindowsPen.cs
- ImageField.cs
- XmlSchemaSimpleContentRestriction.cs
- Compilation.cs
- BamlRecordReader.cs
- Compensate.cs
- CompositeFontInfo.cs
- ScaleTransform.cs
- XmlTextWriter.cs
- EventSinkHelperWriter.cs
- ByteArrayHelperWithString.cs
- XmlDocument.cs
- ServiceHostFactory.cs
- ComponentResourceKey.cs
- DataSetMappper.cs
- Helpers.cs
- ServiceNameElementCollection.cs
- NameValuePair.cs
- X509CertificateValidator.cs
- SubclassTypeValidatorAttribute.cs
- DatatypeImplementation.cs
- OutOfMemoryException.cs
- Operators.cs
- DependencyObjectType.cs
- XPathNavigatorKeyComparer.cs
- WsatServiceAddress.cs
- ScrollBar.cs
- Perspective.cs
- GenericTypeParameterConverter.cs
- EventDescriptor.cs
- ManagementOperationWatcher.cs
- SubMenuStyle.cs
- EntityProviderServices.cs
- XmlRawWriterWrapper.cs
- WindowsListViewGroupSubsetLink.cs
- PageParserFilter.cs
- FrugalList.cs