#if NET20 || NET30 || !NET_4_6 // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Diagnostics; using System.Dynamic.Utils; using LinqInternal.Core; namespace System.Linq.Expressions.Reimplement { /// /// Represents a named parameter expression. /// [DebuggerTypeProxy(typeof(ParameterExpressionProxy))] public class ParameterExpression : Expression { private readonly string _name; internal ParameterExpression(string name) { _name = name; } internal static ParameterExpression Make(Type type, string name, bool isByRef) { if (isByRef) { return new ByRefParameterExpression(type, name); } else { if (!type.IsEnum) { switch (type.GetTypeCode()) { case TypeCode.Boolean: return new PrimitiveParameterExpression(name); case TypeCode.Byte: return new PrimitiveParameterExpression(name); case TypeCode.Char: return new PrimitiveParameterExpression(name); case TypeCode.DateTime: return new PrimitiveParameterExpression(name); case TypeCode.Decimal: return new PrimitiveParameterExpression(name); case TypeCode.Double: return new PrimitiveParameterExpression(name); case TypeCode.Int16: return new PrimitiveParameterExpression(name); case TypeCode.Int32: return new PrimitiveParameterExpression(name); case TypeCode.Int64: return new PrimitiveParameterExpression(name); case TypeCode.Object: // common reference types which we optimize go here. Of course object is in // the list, the others are driven by profiling of various workloads. This list // should be kept short. if (type == typeof(object)) { return new ParameterExpression(name); } else if (type == typeof(Exception)) { return new PrimitiveParameterExpression(name); } else if (type == typeof(object[])) { return new PrimitiveParameterExpression(name); } break; case TypeCode.SByte: return new PrimitiveParameterExpression(name); case TypeCode.Single: return new PrimitiveParameterExpression(name); case TypeCode.String: return new PrimitiveParameterExpression(name); case TypeCode.UInt16: return new PrimitiveParameterExpression(name); case TypeCode.UInt32: return new PrimitiveParameterExpression(name); case TypeCode.UInt64: return new PrimitiveParameterExpression(name); } } } return new TypedParameterExpression(type, name); } /// /// Gets the static type of the expression that this represents. (Inherited from .) /// /// The that represents the static type of the expression. public override Type Type { get { return typeof(object); } } /// /// Returns the node type of this . (Inherited from .) /// /// The that represents this expression. public sealed override ExpressionType NodeType { get { return ExpressionType.Parameter; } } /// /// The Name of the parameter or variable. /// public string Name { get { return _name; } } /// /// Indicates that this ParameterExpression is to be treated as a ByRef parameter. /// public bool IsByRef { get { return GetIsByRef(); } } internal virtual bool GetIsByRef() { return false; } protected internal override Expression Accept(ExpressionVisitor visitor) { return visitor.VisitParameter(this); } } /// /// Specialized subclass to avoid holding onto the byref flag in a /// parameter expression. This version always holds onto the expression /// type explicitly and therefore derives from TypedParameterExpression. /// internal sealed class ByRefParameterExpression : TypedParameterExpression { internal ByRefParameterExpression(Type type, string name) : base(type, name) { } internal override bool GetIsByRef() { return true; } } /// /// Specialized subclass which holds onto the type of the expression for /// uncommon types. /// internal class TypedParameterExpression : ParameterExpression { private readonly Type _paramType; internal TypedParameterExpression(Type type, string name) : base(name) { _paramType = type; } public sealed override Type Type { get { return _paramType; } } } /// /// Generic type to avoid needing explicit storage for primitive data types /// which are commonly used. /// internal sealed class PrimitiveParameterExpression : ParameterExpression { internal PrimitiveParameterExpression(string name) : base(name) { } public override Type Type { get { return typeof(T); } } } public partial class Expression { /// /// Creates a node that can be used to identify a parameter or a variable in an expression tree. /// /// The type of the parameter or variable. /// A node with the specified name and type. public static ParameterExpression Parameter(Type type) { return Parameter(type, null); } /// /// Creates a node that can be used to identify a parameter or a variable in an expression tree. /// /// The type of the parameter or variable. /// A node with the specified name and type. public static ParameterExpression Variable(Type type) { return Variable(type, null); } /// /// Creates a node that can be used to identify a parameter or a variable in an expression tree. /// /// The type of the parameter or variable. /// The name of the parameter or variable, used for debugging or pretty printing purpose only. /// A node with the specified name and type. public static ParameterExpression Parameter(Type type, string name) { ContractUtils.RequiresNotNull(type, "type"); if (type == typeof(void)) { throw Error.ArgumentCannotBeOfTypeVoid(); } var byref = type.IsByRef; if (byref) { type = type.GetElementType(); } return ParameterExpression.Make(type, name, byref); } /// /// Creates a node that can be used to identify a parameter or a variable in an expression tree. /// /// The type of the parameter or variable. /// The name of the parameter or variable, used for debugging or pretty printing purpose only. /// A node with the specified name and type. public static ParameterExpression Variable(Type type, string name) { ContractUtils.RequiresNotNull(type, "type"); if (type == typeof(void)) { throw Error.ArgumentCannotBeOfTypeVoid(); } if (type.IsByRef) { throw Error.TypeMustNotBeByRef(); } return ParameterExpression.Make(type, name, false); } } } #endif