Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Ast / BlockExpression.cs / 1305376 / BlockExpression.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.Collections.ObjectModel; using System.Diagnostics; using System.Dynamic.Utils; using System.Threading; #if SILVERLIGHT using System.Core; #endif namespace System.Linq.Expressions { ////// Represents a block that contains a sequence of expressions where variables can be defined. /// #if !SILVERLIGHT [DebuggerTypeProxy(typeof(Expression.BlockExpressionProxy))] #endif public class BlockExpression : Expression { ////// Gets the expressions in this block. /// public ReadOnlyCollectionExpressions { get { return GetOrMakeExpressions(); } } /// /// Gets the variables defined in this block. /// public ReadOnlyCollectionVariables { get { return GetOrMakeVariables(); } } /// /// Gets the last expression in this block. /// public Expression Result { get { Debug.Assert(ExpressionCount > 0); return GetExpression(ExpressionCount - 1); } } internal BlockExpression() { } ////// Dispatches to the specific visit method for this node type. /// protected internal override Expression Accept(ExpressionVisitor visitor) { return visitor.VisitBlock(this); } ////// Returns the node type of this Expression. Extension nodes should return /// ExpressionType.Extension when overriding this method. /// ///The public sealed override ExpressionType NodeType { get { return ExpressionType.Block; } } ///of the expression. /// Gets the static type of the expression that this ///represents. /// The public override Type Type { get { return GetExpression(ExpressionCount - 1).Type; } } ///that represents the static type of the expression. /// Creates a new expression that is like this one, but using the /// supplied children. If all of the children are the same, it will /// return this expression. /// /// Theproperty of the result. /// The property of the result. /// This expression if no children changed, or an expression with the updated children. public BlockExpression Update(IEnumerablevariables, IEnumerable expressions) { if (variables == Variables && expressions == Expressions) { return this; } return Expression.Block(Type, variables, expressions); } internal virtual Expression GetExpression(int index) { throw ContractUtils.Unreachable; } internal virtual int ExpressionCount { get { throw ContractUtils.Unreachable; } } internal virtual ReadOnlyCollection GetOrMakeExpressions() { throw ContractUtils.Unreachable; } internal virtual ParameterExpression GetVariable(int index) { throw ContractUtils.Unreachable; } internal virtual int VariableCount { get { return 0; } } internal virtual ReadOnlyCollection GetOrMakeVariables() { return EmptyReadOnlyCollection .Instance; } /// /// Makes a copy of this node replacing the parameters/args with the provided values. The /// shape of the parameters/args needs to match the shape of the current block - in other /// words there should be the same # of parameters and args. /// /// parameters can be null in which case the existing parameters are used. /// /// This helper is provided to allow re-writing of nodes to not depend on the specific optimized /// subclass of BlockExpression which is being used. /// internal virtual BlockExpression Rewrite(ReadOnlyCollectionvariables, Expression[] args) { throw ContractUtils.Unreachable; } /// /// Helper used for ensuring we only return 1 instance of a ReadOnlyCollection of T. /// /// This is similar to the ReturnReadOnly which only takes a single argument. This version /// supports nodes which hold onto 5 Expressions and puts all of the arguments into the /// ReadOnlyCollection. /// /// Ultimately this means if we create the readonly collection we will be slightly more wasteful as we'll /// have a readonly collection + some fields in the type. The DLR internally avoids accessing anything /// which would force the readonly collection to be created. /// /// This is used by BlockExpression5 and MethodCallExpression5. /// internal static ReadOnlyCollectionReturnReadOnlyExpressions(BlockExpression provider, ref object collection) { Expression tObj = collection as Expression; if (tObj != null) { // otherwise make sure only one readonly collection ever gets exposed Interlocked.CompareExchange( ref collection, new ReadOnlyCollection (new BlockExpressionList(provider, tObj)), tObj ); } // and return what is not guaranteed to be a readonly collection return (ReadOnlyCollection )collection; } } #region Specialized Subclasses internal sealed class Block2 : BlockExpression { private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider private readonly Expression _arg1; // storage for the 2nd argument. internal Block2(Expression arg0, Expression arg1) { _arg0 = arg0; _arg1 = arg1; } internal override Expression GetExpression(int index) { switch (index) { case 0: return ReturnObject (_arg0); case 1: return _arg1; default: throw new InvalidOperationException(); } } internal override int ExpressionCount { get { return 2; } } internal override ReadOnlyCollection GetOrMakeExpressions() { return ReturnReadOnlyExpressions(this, ref _arg0); } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(args.Length == 2); Debug.Assert(variables == null || variables.Count == 0); return new Block2(args[0], args[1]); } } internal sealed class Block3 : BlockExpression { private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider private readonly Expression _arg1, _arg2; // storage for the 2nd and 3rd arguments. internal Block3(Expression arg0, Expression arg1, Expression arg2) { _arg0 = arg0; _arg1 = arg1; _arg2 = arg2; } internal override Expression GetExpression(int index) { switch (index) { case 0: return ReturnObject (_arg0); case 1: return _arg1; case 2: return _arg2; default: throw new InvalidOperationException(); } } internal override int ExpressionCount { get { return 3; } } internal override ReadOnlyCollection GetOrMakeExpressions() { return ReturnReadOnlyExpressions(this, ref _arg0); } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(args.Length == 3); Debug.Assert(variables == null || variables.Count == 0); return new Block3(args[0], args[1], args[2]); } } internal sealed class Block4 : BlockExpression { private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider private readonly Expression _arg1, _arg2, _arg3; // storarg for the 2nd, 3rd, and 4th arguments. internal Block4(Expression arg0, Expression arg1, Expression arg2, Expression arg3) { _arg0 = arg0; _arg1 = arg1; _arg2 = arg2; _arg3 = arg3; } internal override Expression GetExpression(int index) { switch (index) { case 0: return ReturnObject (_arg0); case 1: return _arg1; case 2: return _arg2; case 3: return _arg3; default: throw new InvalidOperationException(); } } internal override int ExpressionCount { get { return 4; } } internal override ReadOnlyCollection GetOrMakeExpressions() { return ReturnReadOnlyExpressions(this, ref _arg0); } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(args.Length == 4); Debug.Assert(variables == null || variables.Count == 0); return new Block4(args[0], args[1], args[2], args[3]); } } internal sealed class Block5 : BlockExpression { private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider private readonly Expression _arg1, _arg2, _arg3, _arg4; // storage for the 2nd - 5th args. internal Block5(Expression arg0, Expression arg1, Expression arg2, Expression arg3, Expression arg4) { _arg0 = arg0; _arg1 = arg1; _arg2 = arg2; _arg3 = arg3; _arg4 = arg4; } internal override Expression GetExpression(int index) { switch (index) { case 0: return ReturnObject (_arg0); case 1: return _arg1; case 2: return _arg2; case 3: return _arg3; case 4: return _arg4; default: throw new InvalidOperationException(); } } internal override int ExpressionCount { get { return 5; } } internal override ReadOnlyCollection GetOrMakeExpressions() { return ReturnReadOnlyExpressions(this, ref _arg0); } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(args.Length == 5); Debug.Assert(variables == null || variables.Count == 0); return new Block5(args[0], args[1], args[2], args[3], args[4]); } } internal class BlockN : BlockExpression { private IList _expressions; // either the original IList or a ReadOnlyCollection if the user has accessed it. internal BlockN(IList expressions) { Debug.Assert(expressions.Count != 0); _expressions = expressions; } internal override Expression GetExpression(int index) { Debug.Assert(index >= 0 && index < _expressions.Count); return _expressions[index]; } internal override int ExpressionCount { get { return _expressions.Count; } } internal override ReadOnlyCollection GetOrMakeExpressions() { return ReturnReadOnly(ref _expressions); } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(variables == null || variables.Count == 0); return new BlockN(args); } } internal class ScopeExpression : BlockExpression { private IList _variables; // list of variables or ReadOnlyCollection if the user has accessed the readonly collection internal ScopeExpression(IList variables) { _variables = variables; } internal override int VariableCount { get { return _variables.Count; } } internal override ParameterExpression GetVariable(int index) { return _variables[index]; } internal override ReadOnlyCollection GetOrMakeVariables() { return ReturnReadOnly(ref _variables); } protected IList VariablesList { get { return _variables; } } // Used for rewrite of the nodes to either reuse existing set of variables if not rewritten. internal IList ReuseOrValidateVariables(ReadOnlyCollection variables) { if (variables != null && variables != VariablesList) { // Need to validate the new variables (uniqueness, not byref) ValidateVariables(variables, "variables"); return variables; } else { return VariablesList; } } } internal sealed class Scope1 : ScopeExpression { private object _body; internal Scope1(IList variables, Expression body) : base(variables) { _body = body; } internal override Expression GetExpression(int index) { switch (index) { case 0: return ReturnObject (_body); default: throw new InvalidOperationException(); } } internal override int ExpressionCount { get { return 1; } } internal override ReadOnlyCollection GetOrMakeExpressions() { return ReturnReadOnlyExpressions(this, ref _body); } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(args.Length == 1); Debug.Assert(variables == null || variables.Count == VariableCount); return new Scope1(ReuseOrValidateVariables(variables), args[0]); } } internal class ScopeN : ScopeExpression { private IList _body; internal ScopeN(IList variables, IList body) : base(variables) { _body = body; } internal override Expression GetExpression(int index) { return _body[index]; } internal override int ExpressionCount { get { return _body.Count; } } internal override ReadOnlyCollection GetOrMakeExpressions() { return ReturnReadOnly(ref _body); } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(args.Length == ExpressionCount); Debug.Assert(variables == null || variables.Count == VariableCount); return new ScopeN(ReuseOrValidateVariables(variables), args); } } internal class ScopeWithType : ScopeN { private readonly Type _type; internal ScopeWithType(IList variables, IList expressions, Type type) : base(variables, expressions) { _type = type; } public sealed override Type Type { get { return _type; } } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(args.Length == ExpressionCount); Debug.Assert(variables == null || variables.Count == VariableCount); return new ScopeWithType(ReuseOrValidateVariables(variables), args, _type); } } #endregion #region Block List Classes /// /// Provides a wrapper around an IArgumentProvider which exposes the argument providers /// members out as an IList of Expression. This is used to avoid allocating an array /// which needs to be stored inside of a ReadOnlyCollection. Instead this type has /// the same amount of overhead as an array without duplicating the storage of the /// elements. This ensures that internally we can avoid creating and copying arrays /// while users of the Expression trees also don't pay a size penalty for this internal /// optimization. See IArgumentProvider for more general information on the Expression /// tree optimizations being used here. /// internal class BlockExpressionList : IList{ private readonly BlockExpression _block; private readonly Expression _arg0; internal BlockExpressionList(BlockExpression provider, Expression arg0) { _block = provider; _arg0 = arg0; } #region IList Members public int IndexOf(Expression item) { if (_arg0 == item) { return 0; } for (int i = 1; i < _block.ExpressionCount; i++) { if (_block.GetExpression(i) == item) { return i; } } return -1; } public void Insert(int index, Expression item) { throw ContractUtils.Unreachable; } public void RemoveAt(int index) { throw ContractUtils.Unreachable; } public Expression this[int index] { get { if (index == 0) { return _arg0; } return _block.GetExpression(index); } set { throw ContractUtils.Unreachable; } } #endregion #region ICollection Members public void Add(Expression item) { throw ContractUtils.Unreachable; } public void Clear() { throw ContractUtils.Unreachable; } public bool Contains(Expression item) { return IndexOf(item) != -1; } public void CopyTo(Expression[] array, int arrayIndex) { array[arrayIndex++] = _arg0; for (int i = 1; i < _block.ExpressionCount; i++) { array[arrayIndex++] = _block.GetExpression(i); } } public int Count { get { return _block.ExpressionCount; } } public bool IsReadOnly { get { return true; } } public bool Remove(Expression item) { throw ContractUtils.Unreachable; } #endregion #region IEnumerable Members public IEnumerator GetEnumerator() { yield return _arg0; for (int i = 1; i < _block.ExpressionCount; i++) { yield return _block.GetExpression(i); } } #endregion #region IEnumerable Members System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { yield return _arg0; for (int i = 1; i < _block.ExpressionCount; i++) { yield return _block.GetExpression(i); } } #endregion } #endregion public partial class Expression { /// /// Creates a /// The first expression in the block. /// The second expression in the block. ///that contains two expressions and has no variables. /// The created public static BlockExpression Block(Expression arg0, Expression arg1) { RequiresCanRead(arg0, "arg0"); RequiresCanRead(arg1, "arg1"); return new Block2(arg0, arg1); } ///. /// Creates a /// The first expression in the block. /// The second expression in the block. /// The third expression in the block. ///that contains three expressions and has no variables. /// The created public static BlockExpression Block(Expression arg0, Expression arg1, Expression arg2) { RequiresCanRead(arg0, "arg0"); RequiresCanRead(arg1, "arg1"); RequiresCanRead(arg2, "arg2"); return new Block3(arg0, arg1, arg2); } ///. /// Creates a /// The first expression in the block. /// The second expression in the block. /// The third expression in the block. /// The fourth expression in the block. ///that contains four expressions and has no variables. /// The created public static BlockExpression Block(Expression arg0, Expression arg1, Expression arg2, Expression arg3) { RequiresCanRead(arg0, "arg0"); RequiresCanRead(arg1, "arg1"); RequiresCanRead(arg2, "arg2"); RequiresCanRead(arg3, "arg3"); return new Block4(arg0, arg1, arg2, arg3); } ///. /// Creates a /// The first expression in the block. /// The second expression in the block. /// The third expression in the block. /// The fourth expression in the block. /// The fifth expression in the block. ///that contains five expressions and has no variables. /// The created public static BlockExpression Block(Expression arg0, Expression arg1, Expression arg2, Expression arg3, Expression arg4) { RequiresCanRead(arg0, "arg0"); RequiresCanRead(arg1, "arg1"); RequiresCanRead(arg2, "arg2"); RequiresCanRead(arg3, "arg3"); RequiresCanRead(arg4, "arg4"); return new Block5(arg0, arg1, arg2, arg3, arg4); } ///. /// Creates a /// The expressions in the block. ///that contains the given expressions and has no variables. /// The created public static BlockExpression Block(params Expression[] expressions) { ContractUtils.RequiresNotNull(expressions, "expressions"); switch (expressions.Length) { case 2: return Block(expressions[0], expressions[1]); case 3: return Block(expressions[0], expressions[1], expressions[2]); case 4: return Block(expressions[0], expressions[1], expressions[2], expressions[3]); case 5: return Block(expressions[0], expressions[1], expressions[2], expressions[3], expressions[4]); default: ContractUtils.RequiresNotEmpty(expressions, "expressions"); RequiresCanRead(expressions, "expressions"); return new BlockN(expressions.Copy()); } } ///. /// Creates a /// The expressions in the block. ///that contains the given expressions and has no variables. /// The created public static BlockExpression Block(IEnumerable. expressions) { return Block(EmptyReadOnlyCollection .Instance, expressions); } /// /// Creates a /// The result type of the block. /// The expressions in the block. ///that contains the given expressions, has no variables and has specific result type. /// The created public static BlockExpression Block(Type type, params Expression[] expressions) { ContractUtils.RequiresNotNull(expressions, "expressions"); return Block(type, (IEnumerable. )expressions); } /// /// Creates a /// The result type of the block. /// The expressions in the block. ///that contains the given expressions, has no variables and has specific result type. /// The created public static BlockExpression Block(Type type, IEnumerable. expressions) { return Block(type, EmptyReadOnlyCollection .Instance, expressions); } /// /// Creates a /// The variables in the block. /// The expressions in the block. ///that contains the given variables and expressions. /// The created public static BlockExpression Block(IEnumerable. variables, params Expression[] expressions) { return Block(variables, (IEnumerable )expressions); } /// /// Creates a /// The result type of the block. /// The variables in the block. /// The expressions in the block. ///that contains the given variables and expressions. /// The created public static BlockExpression Block(Type type, IEnumerable. variables, params Expression[] expressions) { return Block(type, variables, (IEnumerable )expressions); } /// /// Creates a /// The variables in the block. /// The expressions in the block. ///that contains the given variables and expressions. /// The created public static BlockExpression Block(IEnumerable. variables, IEnumerable expressions) { ContractUtils.RequiresNotNull(expressions, "expressions"); var expressionList = expressions.ToReadOnly(); ContractUtils.RequiresNotEmpty(expressionList, "expressions"); RequiresCanRead(expressionList, "expressions"); return Block(expressionList.Last().Type, variables, expressionList); } /// /// Creates a /// The result type of the block. /// The variables in the block. /// The expressions in the block. ///that contains the given variables and expressions. /// The created public static BlockExpression Block(Type type, IEnumerable. variables, IEnumerable expressions) { ContractUtils.RequiresNotNull(type, "type"); ContractUtils.RequiresNotNull(expressions, "expressions"); var expressionList = expressions.ToReadOnly(); var variableList = variables.ToReadOnly(); ContractUtils.RequiresNotEmpty(expressionList, "expressions"); RequiresCanRead(expressionList, "expressions"); ValidateVariables(variableList, "variables"); Expression last = expressionList.Last(); if (type != typeof(void)) { if (!TypeUtils.AreReferenceAssignable(type, last.Type)) { throw Error.ArgumentTypesMustMatch(); } } if (!TypeUtils.AreEquivalent(type, last.Type)) { return new ScopeWithType(variableList, expressionList, type); } else { if (expressionList.Count == 1) { return new Scope1(variableList, expressionList[0]); } else { return new ScopeN(variableList, expressionList); } } } // Checks that all variables are non-null, not byref, and unique. internal static void ValidateVariables(ReadOnlyCollection varList, string collectionName) { if (varList.Count == 0) { return; } int count = varList.Count; var set = new Set (count); for (int i = 0; i < count; i++) { ParameterExpression v = varList[i]; if (v == null) { throw new ArgumentNullException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0}[{1}]", collectionName, set.Count)); } if (v.IsByRef) { throw Error.VariableMustNotBeByRef(v, v.Type); } if (set.Contains(v)) { throw Error.DuplicateVariable(v); } set.Add(v); } } } } // 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.Collections.ObjectModel; using System.Diagnostics; using System.Dynamic.Utils; using System.Threading; #if SILVERLIGHT using System.Core; #endif namespace System.Linq.Expressions { /// /// Represents a block that contains a sequence of expressions where variables can be defined. /// #if !SILVERLIGHT [DebuggerTypeProxy(typeof(Expression.BlockExpressionProxy))] #endif public class BlockExpression : Expression { ////// Gets the expressions in this block. /// public ReadOnlyCollectionExpressions { get { return GetOrMakeExpressions(); } } /// /// Gets the variables defined in this block. /// public ReadOnlyCollectionVariables { get { return GetOrMakeVariables(); } } /// /// Gets the last expression in this block. /// public Expression Result { get { Debug.Assert(ExpressionCount > 0); return GetExpression(ExpressionCount - 1); } } internal BlockExpression() { } ////// Dispatches to the specific visit method for this node type. /// protected internal override Expression Accept(ExpressionVisitor visitor) { return visitor.VisitBlock(this); } ////// Returns the node type of this Expression. Extension nodes should return /// ExpressionType.Extension when overriding this method. /// ///The public sealed override ExpressionType NodeType { get { return ExpressionType.Block; } } ///of the expression. /// Gets the static type of the expression that this ///represents. /// The public override Type Type { get { return GetExpression(ExpressionCount - 1).Type; } } ///that represents the static type of the expression. /// Creates a new expression that is like this one, but using the /// supplied children. If all of the children are the same, it will /// return this expression. /// /// Theproperty of the result. /// The property of the result. /// This expression if no children changed, or an expression with the updated children. public BlockExpression Update(IEnumerablevariables, IEnumerable expressions) { if (variables == Variables && expressions == Expressions) { return this; } return Expression.Block(Type, variables, expressions); } internal virtual Expression GetExpression(int index) { throw ContractUtils.Unreachable; } internal virtual int ExpressionCount { get { throw ContractUtils.Unreachable; } } internal virtual ReadOnlyCollection GetOrMakeExpressions() { throw ContractUtils.Unreachable; } internal virtual ParameterExpression GetVariable(int index) { throw ContractUtils.Unreachable; } internal virtual int VariableCount { get { return 0; } } internal virtual ReadOnlyCollection GetOrMakeVariables() { return EmptyReadOnlyCollection .Instance; } /// /// Makes a copy of this node replacing the parameters/args with the provided values. The /// shape of the parameters/args needs to match the shape of the current block - in other /// words there should be the same # of parameters and args. /// /// parameters can be null in which case the existing parameters are used. /// /// This helper is provided to allow re-writing of nodes to not depend on the specific optimized /// subclass of BlockExpression which is being used. /// internal virtual BlockExpression Rewrite(ReadOnlyCollectionvariables, Expression[] args) { throw ContractUtils.Unreachable; } /// /// Helper used for ensuring we only return 1 instance of a ReadOnlyCollection of T. /// /// This is similar to the ReturnReadOnly which only takes a single argument. This version /// supports nodes which hold onto 5 Expressions and puts all of the arguments into the /// ReadOnlyCollection. /// /// Ultimately this means if we create the readonly collection we will be slightly more wasteful as we'll /// have a readonly collection + some fields in the type. The DLR internally avoids accessing anything /// which would force the readonly collection to be created. /// /// This is used by BlockExpression5 and MethodCallExpression5. /// internal static ReadOnlyCollectionReturnReadOnlyExpressions(BlockExpression provider, ref object collection) { Expression tObj = collection as Expression; if (tObj != null) { // otherwise make sure only one readonly collection ever gets exposed Interlocked.CompareExchange( ref collection, new ReadOnlyCollection (new BlockExpressionList(provider, tObj)), tObj ); } // and return what is not guaranteed to be a readonly collection return (ReadOnlyCollection )collection; } } #region Specialized Subclasses internal sealed class Block2 : BlockExpression { private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider private readonly Expression _arg1; // storage for the 2nd argument. internal Block2(Expression arg0, Expression arg1) { _arg0 = arg0; _arg1 = arg1; } internal override Expression GetExpression(int index) { switch (index) { case 0: return ReturnObject (_arg0); case 1: return _arg1; default: throw new InvalidOperationException(); } } internal override int ExpressionCount { get { return 2; } } internal override ReadOnlyCollection GetOrMakeExpressions() { return ReturnReadOnlyExpressions(this, ref _arg0); } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(args.Length == 2); Debug.Assert(variables == null || variables.Count == 0); return new Block2(args[0], args[1]); } } internal sealed class Block3 : BlockExpression { private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider private readonly Expression _arg1, _arg2; // storage for the 2nd and 3rd arguments. internal Block3(Expression arg0, Expression arg1, Expression arg2) { _arg0 = arg0; _arg1 = arg1; _arg2 = arg2; } internal override Expression GetExpression(int index) { switch (index) { case 0: return ReturnObject (_arg0); case 1: return _arg1; case 2: return _arg2; default: throw new InvalidOperationException(); } } internal override int ExpressionCount { get { return 3; } } internal override ReadOnlyCollection GetOrMakeExpressions() { return ReturnReadOnlyExpressions(this, ref _arg0); } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(args.Length == 3); Debug.Assert(variables == null || variables.Count == 0); return new Block3(args[0], args[1], args[2]); } } internal sealed class Block4 : BlockExpression { private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider private readonly Expression _arg1, _arg2, _arg3; // storarg for the 2nd, 3rd, and 4th arguments. internal Block4(Expression arg0, Expression arg1, Expression arg2, Expression arg3) { _arg0 = arg0; _arg1 = arg1; _arg2 = arg2; _arg3 = arg3; } internal override Expression GetExpression(int index) { switch (index) { case 0: return ReturnObject (_arg0); case 1: return _arg1; case 2: return _arg2; case 3: return _arg3; default: throw new InvalidOperationException(); } } internal override int ExpressionCount { get { return 4; } } internal override ReadOnlyCollection GetOrMakeExpressions() { return ReturnReadOnlyExpressions(this, ref _arg0); } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(args.Length == 4); Debug.Assert(variables == null || variables.Count == 0); return new Block4(args[0], args[1], args[2], args[3]); } } internal sealed class Block5 : BlockExpression { private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider private readonly Expression _arg1, _arg2, _arg3, _arg4; // storage for the 2nd - 5th args. internal Block5(Expression arg0, Expression arg1, Expression arg2, Expression arg3, Expression arg4) { _arg0 = arg0; _arg1 = arg1; _arg2 = arg2; _arg3 = arg3; _arg4 = arg4; } internal override Expression GetExpression(int index) { switch (index) { case 0: return ReturnObject (_arg0); case 1: return _arg1; case 2: return _arg2; case 3: return _arg3; case 4: return _arg4; default: throw new InvalidOperationException(); } } internal override int ExpressionCount { get { return 5; } } internal override ReadOnlyCollection GetOrMakeExpressions() { return ReturnReadOnlyExpressions(this, ref _arg0); } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(args.Length == 5); Debug.Assert(variables == null || variables.Count == 0); return new Block5(args[0], args[1], args[2], args[3], args[4]); } } internal class BlockN : BlockExpression { private IList _expressions; // either the original IList or a ReadOnlyCollection if the user has accessed it. internal BlockN(IList expressions) { Debug.Assert(expressions.Count != 0); _expressions = expressions; } internal override Expression GetExpression(int index) { Debug.Assert(index >= 0 && index < _expressions.Count); return _expressions[index]; } internal override int ExpressionCount { get { return _expressions.Count; } } internal override ReadOnlyCollection GetOrMakeExpressions() { return ReturnReadOnly(ref _expressions); } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(variables == null || variables.Count == 0); return new BlockN(args); } } internal class ScopeExpression : BlockExpression { private IList _variables; // list of variables or ReadOnlyCollection if the user has accessed the readonly collection internal ScopeExpression(IList variables) { _variables = variables; } internal override int VariableCount { get { return _variables.Count; } } internal override ParameterExpression GetVariable(int index) { return _variables[index]; } internal override ReadOnlyCollection GetOrMakeVariables() { return ReturnReadOnly(ref _variables); } protected IList VariablesList { get { return _variables; } } // Used for rewrite of the nodes to either reuse existing set of variables if not rewritten. internal IList ReuseOrValidateVariables(ReadOnlyCollection variables) { if (variables != null && variables != VariablesList) { // Need to validate the new variables (uniqueness, not byref) ValidateVariables(variables, "variables"); return variables; } else { return VariablesList; } } } internal sealed class Scope1 : ScopeExpression { private object _body; internal Scope1(IList variables, Expression body) : base(variables) { _body = body; } internal override Expression GetExpression(int index) { switch (index) { case 0: return ReturnObject (_body); default: throw new InvalidOperationException(); } } internal override int ExpressionCount { get { return 1; } } internal override ReadOnlyCollection GetOrMakeExpressions() { return ReturnReadOnlyExpressions(this, ref _body); } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(args.Length == 1); Debug.Assert(variables == null || variables.Count == VariableCount); return new Scope1(ReuseOrValidateVariables(variables), args[0]); } } internal class ScopeN : ScopeExpression { private IList _body; internal ScopeN(IList variables, IList body) : base(variables) { _body = body; } internal override Expression GetExpression(int index) { return _body[index]; } internal override int ExpressionCount { get { return _body.Count; } } internal override ReadOnlyCollection GetOrMakeExpressions() { return ReturnReadOnly(ref _body); } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(args.Length == ExpressionCount); Debug.Assert(variables == null || variables.Count == VariableCount); return new ScopeN(ReuseOrValidateVariables(variables), args); } } internal class ScopeWithType : ScopeN { private readonly Type _type; internal ScopeWithType(IList variables, IList expressions, Type type) : base(variables, expressions) { _type = type; } public sealed override Type Type { get { return _type; } } internal override BlockExpression Rewrite(ReadOnlyCollection variables, Expression[] args) { Debug.Assert(args.Length == ExpressionCount); Debug.Assert(variables == null || variables.Count == VariableCount); return new ScopeWithType(ReuseOrValidateVariables(variables), args, _type); } } #endregion #region Block List Classes /// /// Provides a wrapper around an IArgumentProvider which exposes the argument providers /// members out as an IList of Expression. This is used to avoid allocating an array /// which needs to be stored inside of a ReadOnlyCollection. Instead this type has /// the same amount of overhead as an array without duplicating the storage of the /// elements. This ensures that internally we can avoid creating and copying arrays /// while users of the Expression trees also don't pay a size penalty for this internal /// optimization. See IArgumentProvider for more general information on the Expression /// tree optimizations being used here. /// internal class BlockExpressionList : IList{ private readonly BlockExpression _block; private readonly Expression _arg0; internal BlockExpressionList(BlockExpression provider, Expression arg0) { _block = provider; _arg0 = arg0; } #region IList Members public int IndexOf(Expression item) { if (_arg0 == item) { return 0; } for (int i = 1; i < _block.ExpressionCount; i++) { if (_block.GetExpression(i) == item) { return i; } } return -1; } public void Insert(int index, Expression item) { throw ContractUtils.Unreachable; } public void RemoveAt(int index) { throw ContractUtils.Unreachable; } public Expression this[int index] { get { if (index == 0) { return _arg0; } return _block.GetExpression(index); } set { throw ContractUtils.Unreachable; } } #endregion #region ICollection Members public void Add(Expression item) { throw ContractUtils.Unreachable; } public void Clear() { throw ContractUtils.Unreachable; } public bool Contains(Expression item) { return IndexOf(item) != -1; } public void CopyTo(Expression[] array, int arrayIndex) { array[arrayIndex++] = _arg0; for (int i = 1; i < _block.ExpressionCount; i++) { array[arrayIndex++] = _block.GetExpression(i); } } public int Count { get { return _block.ExpressionCount; } } public bool IsReadOnly { get { return true; } } public bool Remove(Expression item) { throw ContractUtils.Unreachable; } #endregion #region IEnumerable Members public IEnumerator GetEnumerator() { yield return _arg0; for (int i = 1; i < _block.ExpressionCount; i++) { yield return _block.GetExpression(i); } } #endregion #region IEnumerable Members System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { yield return _arg0; for (int i = 1; i < _block.ExpressionCount; i++) { yield return _block.GetExpression(i); } } #endregion } #endregion public partial class Expression { /// /// Creates a /// The first expression in the block. /// The second expression in the block. ///that contains two expressions and has no variables. /// The created public static BlockExpression Block(Expression arg0, Expression arg1) { RequiresCanRead(arg0, "arg0"); RequiresCanRead(arg1, "arg1"); return new Block2(arg0, arg1); } ///. /// Creates a /// The first expression in the block. /// The second expression in the block. /// The third expression in the block. ///that contains three expressions and has no variables. /// The created public static BlockExpression Block(Expression arg0, Expression arg1, Expression arg2) { RequiresCanRead(arg0, "arg0"); RequiresCanRead(arg1, "arg1"); RequiresCanRead(arg2, "arg2"); return new Block3(arg0, arg1, arg2); } ///. /// Creates a /// The first expression in the block. /// The second expression in the block. /// The third expression in the block. /// The fourth expression in the block. ///that contains four expressions and has no variables. /// The created public static BlockExpression Block(Expression arg0, Expression arg1, Expression arg2, Expression arg3) { RequiresCanRead(arg0, "arg0"); RequiresCanRead(arg1, "arg1"); RequiresCanRead(arg2, "arg2"); RequiresCanRead(arg3, "arg3"); return new Block4(arg0, arg1, arg2, arg3); } ///. /// Creates a /// The first expression in the block. /// The second expression in the block. /// The third expression in the block. /// The fourth expression in the block. /// The fifth expression in the block. ///that contains five expressions and has no variables. /// The created public static BlockExpression Block(Expression arg0, Expression arg1, Expression arg2, Expression arg3, Expression arg4) { RequiresCanRead(arg0, "arg0"); RequiresCanRead(arg1, "arg1"); RequiresCanRead(arg2, "arg2"); RequiresCanRead(arg3, "arg3"); RequiresCanRead(arg4, "arg4"); return new Block5(arg0, arg1, arg2, arg3, arg4); } ///. /// Creates a /// The expressions in the block. ///that contains the given expressions and has no variables. /// The created public static BlockExpression Block(params Expression[] expressions) { ContractUtils.RequiresNotNull(expressions, "expressions"); switch (expressions.Length) { case 2: return Block(expressions[0], expressions[1]); case 3: return Block(expressions[0], expressions[1], expressions[2]); case 4: return Block(expressions[0], expressions[1], expressions[2], expressions[3]); case 5: return Block(expressions[0], expressions[1], expressions[2], expressions[3], expressions[4]); default: ContractUtils.RequiresNotEmpty(expressions, "expressions"); RequiresCanRead(expressions, "expressions"); return new BlockN(expressions.Copy()); } } ///. /// Creates a /// The expressions in the block. ///that contains the given expressions and has no variables. /// The created public static BlockExpression Block(IEnumerable. expressions) { return Block(EmptyReadOnlyCollection .Instance, expressions); } /// /// Creates a /// The result type of the block. /// The expressions in the block. ///that contains the given expressions, has no variables and has specific result type. /// The created public static BlockExpression Block(Type type, params Expression[] expressions) { ContractUtils.RequiresNotNull(expressions, "expressions"); return Block(type, (IEnumerable. )expressions); } /// /// Creates a /// The result type of the block. /// The expressions in the block. ///that contains the given expressions, has no variables and has specific result type. /// The created public static BlockExpression Block(Type type, IEnumerable. expressions) { return Block(type, EmptyReadOnlyCollection .Instance, expressions); } /// /// Creates a /// The variables in the block. /// The expressions in the block. ///that contains the given variables and expressions. /// The created public static BlockExpression Block(IEnumerable. variables, params Expression[] expressions) { return Block(variables, (IEnumerable )expressions); } /// /// Creates a /// The result type of the block. /// The variables in the block. /// The expressions in the block. ///that contains the given variables and expressions. /// The created public static BlockExpression Block(Type type, IEnumerable. variables, params Expression[] expressions) { return Block(type, variables, (IEnumerable )expressions); } /// /// Creates a /// The variables in the block. /// The expressions in the block. ///that contains the given variables and expressions. /// The created public static BlockExpression Block(IEnumerable. variables, IEnumerable expressions) { ContractUtils.RequiresNotNull(expressions, "expressions"); var expressionList = expressions.ToReadOnly(); ContractUtils.RequiresNotEmpty(expressionList, "expressions"); RequiresCanRead(expressionList, "expressions"); return Block(expressionList.Last().Type, variables, expressionList); } /// /// Creates a /// The result type of the block. /// The variables in the block. /// The expressions in the block. ///that contains the given variables and expressions. /// The created public static BlockExpression Block(Type type, IEnumerable. variables, IEnumerable expressions) { ContractUtils.RequiresNotNull(type, "type"); ContractUtils.RequiresNotNull(expressions, "expressions"); var expressionList = expressions.ToReadOnly(); var variableList = variables.ToReadOnly(); ContractUtils.RequiresNotEmpty(expressionList, "expressions"); RequiresCanRead(expressionList, "expressions"); ValidateVariables(variableList, "variables"); Expression last = expressionList.Last(); if (type != typeof(void)) { if (!TypeUtils.AreReferenceAssignable(type, last.Type)) { throw Error.ArgumentTypesMustMatch(); } } if (!TypeUtils.AreEquivalent(type, last.Type)) { return new ScopeWithType(variableList, expressionList, type); } else { if (expressionList.Count == 1) { return new Scope1(variableList, expressionList[0]); } else { return new ScopeN(variableList, expressionList); } } } // Checks that all variables are non-null, not byref, and unique. internal static void ValidateVariables(ReadOnlyCollection varList, string collectionName) { if (varList.Count == 0) { return; } int count = varList.Count; var set = new Set (count); for (int i = 0; i < count; i++) { ParameterExpression v = varList[i]; if (v == null) { throw new ArgumentNullException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0}[{1}]", collectionName, set.Count)); } if (v.IsByRef) { throw Error.VariableMustNotBeByRef(v, v.Type); } if (set.Contains(v)) { throw Error.DuplicateVariable(v); } set.Add(v); } } } } // 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
- LambdaCompiler.Generated.cs
- RowParagraph.cs
- ReadOnlyDataSource.cs
- AsyncDataRequest.cs
- AppLevelCompilationSectionCache.cs
- FormViewCommandEventArgs.cs
- Variant.cs
- ListViewItemEventArgs.cs
- ImageSourceValueSerializer.cs
- transactioncontext.cs
- DecimalKeyFrameCollection.cs
- WebPartVerbsEventArgs.cs
- ContentValidator.cs
- DbFunctionCommandTree.cs
- GroupBox.cs
- Point4DValueSerializer.cs
- ContextQuery.cs
- SQLMembershipProvider.cs
- ConnectionManagementSection.cs
- TypeInfo.cs
- DataGridViewTopLeftHeaderCell.cs
- VersionConverter.cs
- DataGridViewControlCollection.cs
- SafeRightsManagementPubHandle.cs
- MailHeaderInfo.cs
- StdValidatorsAndConverters.cs
- ServiceCredentialsSecurityTokenManager.cs
- WebPartVerbCollection.cs
- CharacterMetrics.cs
- ToggleProviderWrapper.cs
- EmptyStringExpandableObjectConverter.cs
- DisplayInformation.cs
- TerminateSequence.cs
- FontUnitConverter.cs
- Policy.cs
- AlphaSortedEnumConverter.cs
- ControlIdConverter.cs
- SqlSelectClauseBuilder.cs
- SqlNodeAnnotation.cs
- BackgroundWorker.cs
- SqlAliasesReferenced.cs
- BooleanExpr.cs
- SchemaImporterExtensionElementCollection.cs
- MsmqIntegrationBindingElement.cs
- IItemContainerGenerator.cs
- ChtmlTextBoxAdapter.cs
- FormViewInsertEventArgs.cs
- CodeBlockBuilder.cs
- ListViewSortEventArgs.cs
- TimeStampChecker.cs
- SystemIPv6InterfaceProperties.cs
- ErrorHandler.cs
- TemplateBindingExpression.cs
- MobilePage.cs
- TraceSource.cs
- Accessible.cs
- TableTextElementCollectionInternal.cs
- columnmapkeybuilder.cs
- LayoutTable.cs
- DependencyObjectProvider.cs
- XmlCustomFormatter.cs
- StatusStrip.cs
- DesignBindingPicker.cs
- DCSafeHandle.cs
- MD5.cs
- SoapIgnoreAttribute.cs
- AvtEvent.cs
- BasicExpandProvider.cs
- QueryStringParameter.cs
- XamlGridLengthSerializer.cs
- DATA_BLOB.cs
- XdrBuilder.cs
- ExpressionVisitorHelpers.cs
- GregorianCalendar.cs
- SinglePhaseEnlistment.cs
- EnumerableRowCollection.cs
- SharedPersonalizationStateInfo.cs
- EntityModelBuildProvider.cs
- BamlResourceContent.cs
- PasswordBoxAutomationPeer.cs
- LeaseManager.cs
- BufferedReceiveManager.cs
- XmlSchemaAppInfo.cs
- RuleCache.cs
- DataTemplateKey.cs
- PocoPropertyAccessorStrategy.cs
- DataGridTablesFactory.cs
- NotifyIcon.cs
- PerfProviderCollection.cs
- ConfigurationLocation.cs
- DateTimeFormat.cs
- OleDbParameter.cs
- DrawingContextDrawingContextWalker.cs
- DateTime.cs
- ConfigXmlElement.cs
- SourceExpressionException.cs
- DockProviderWrapper.cs
- XmlCharCheckingWriter.cs
- IsolationInterop.cs
- Zone.cs