1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Apache License, Version 2.0, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Apache License, Version 2.0.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
17 using System.Diagnostics;
18 using System.Dynamic.Utils;
21 namespace Microsoft.Scripting.Ast {
23 namespace System.Linq.Expressions {
27 /// Represents a named parameter expression.
29 [DebuggerTypeProxy(typeof(Expression.ParameterExpressionProxy))]
30 public class ParameterExpression : Expression {
31 private readonly string _name;
33 internal ParameterExpression(string name) {
37 internal static ParameterExpression Make(Type type, string name, bool isByRef) {
39 return new ByRefParameterExpression(type, name);
42 switch (Type.GetTypeCode(type)) {
43 case TypeCode.Boolean: return new PrimitiveParameterExpression<Boolean>(name);
44 case TypeCode.Byte: return new PrimitiveParameterExpression<Byte>(name);
45 case TypeCode.Char: return new PrimitiveParameterExpression<Char>(name);
46 case TypeCode.DateTime: return new PrimitiveParameterExpression<DateTime>(name);
47 case TypeCode.DBNull: return new PrimitiveParameterExpression<DBNull>(name);
48 case TypeCode.Decimal: return new PrimitiveParameterExpression<Decimal>(name);
49 case TypeCode.Double: return new PrimitiveParameterExpression<Double>(name);
50 case TypeCode.Int16: return new PrimitiveParameterExpression<Int16>(name);
51 case TypeCode.Int32: return new PrimitiveParameterExpression<Int32>(name);
52 case TypeCode.Int64: return new PrimitiveParameterExpression<Int64>(name);
54 // common reference types which we optimize go here. Of course object is in
55 // the list, the others are driven by profiling of various workloads. This list
56 // should be kept short.
57 if (type == typeof(object)) {
58 return new ParameterExpression(name);
59 } else if (type == typeof(Exception)) {
60 return new PrimitiveParameterExpression<Exception>(name);
61 } else if (type == typeof(object[])) {
62 return new PrimitiveParameterExpression<object[]>(name);
65 case TypeCode.SByte: return new PrimitiveParameterExpression<SByte>(name);
66 case TypeCode.Single: return new PrimitiveParameterExpression<Single>(name);
67 case TypeCode.String: return new PrimitiveParameterExpression<String>(name);
68 case TypeCode.UInt16: return new PrimitiveParameterExpression<UInt16>(name);
69 case TypeCode.UInt32: return new PrimitiveParameterExpression<UInt32>(name);
70 case TypeCode.UInt64: return new PrimitiveParameterExpression<UInt64>(name);
75 return new TypedParameterExpression(type, name);
79 /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
81 /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
82 public override Type Type {
83 get { return typeof(object); }
87 /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
89 /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
90 public sealed override ExpressionType NodeType {
91 get { return ExpressionType.Parameter; }
95 /// The Name of the parameter or variable.
102 /// Indicates that this ParameterExpression is to be treated as a ByRef parameter.
104 public bool IsByRef {
110 internal virtual bool GetIsByRef() {
115 /// Dispatches to the specific visit method for this node type.
117 protected internal override Expression Accept(ExpressionVisitor visitor) {
118 return visitor.VisitParameter(this);
123 /// Specialized subclass to avoid holding onto the byref flag in a
124 /// parameter expression. This version always holds onto the expression
125 /// type explicitly and therefore derives from TypedParameterExpression.
127 internal sealed class ByRefParameterExpression : TypedParameterExpression {
128 internal ByRefParameterExpression(Type type, string name)
132 internal override bool GetIsByRef() {
138 /// Specialized subclass which holds onto the type of the expression for
141 internal class TypedParameterExpression : ParameterExpression {
142 private readonly Type _paramType;
144 internal TypedParameterExpression(Type type, string name)
149 public sealed override Type Type {
150 get { return _paramType; }
155 /// Generic type to avoid needing explicit storage for primitive data types
156 /// which are commonly used.
158 internal sealed class PrimitiveParameterExpression<T> : ParameterExpression {
159 internal PrimitiveParameterExpression(string name)
163 public sealed override Type Type {
164 get { return typeof(T); }
168 public partial class Expression {
171 /// Creates a <see cref="ParameterExpression" /> node that can be used to identify a parameter or a variable in an expression tree.
173 /// <param name="type">The type of the parameter or variable.</param>
174 /// <returns>A <see cref="ParameterExpression" /> node with the specified name and type.</returns>
175 public static ParameterExpression Parameter(Type type) {
176 return Parameter(type, null);
180 /// Creates a <see cref="ParameterExpression" /> node that can be used to identify a parameter or a variable in an expression tree.
182 /// <param name="type">The type of the parameter or variable.</param>
183 /// <returns>A <see cref="ParameterExpression" /> node with the specified name and type.</returns>
184 public static ParameterExpression Variable(Type type) {
185 return Variable(type, null);
189 /// Creates a <see cref="ParameterExpression" /> node that can be used to identify a parameter or a variable in an expression tree.
191 /// <param name="type">The type of the parameter or variable.</param>
192 /// <param name="name">The name of the parameter or variable, used for debugging or pretty printing purpose only.</param>
193 /// <returns>A <see cref="ParameterExpression" /> node with the specified name and type.</returns>
194 public static ParameterExpression Parameter(Type type, string name) {
195 ContractUtils.RequiresNotNull(type, "type");
197 if (type == typeof(void)) {
198 throw Error.ArgumentCannotBeOfTypeVoid();
201 bool byref = type.IsByRef;
203 type = type.GetElementType();
206 return ParameterExpression.Make(type, name, byref);
210 /// Creates a <see cref="ParameterExpression" /> node that can be used to identify a parameter or a variable in an expression tree.
212 /// <param name="type">The type of the parameter or variable.</param>
213 /// <param name="name">The name of the parameter or variable, used for debugging or pretty printing purpose only.</param>
214 /// <returns>A <see cref="ParameterExpression" /> node with the specified name and type.</returns>
215 public static ParameterExpression Variable(Type type, string name) {
216 ContractUtils.RequiresNotNull(type, "type");
217 if (type == typeof(void)) throw Error.ArgumentCannotBeOfTypeVoid();
218 if (type.IsByRef) throw Error.TypeMustNotBeByRef();
219 return ParameterExpression.Make(type, name, false);