PageRenderTime 54ms CodeModel.GetById 28ms app.highlight 19ms RepoModel.GetById 3ms app.codeStats 0ms

/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/InvocationExpression.cs

https://github.com/enricosada/mono
C# | 199 lines | 87 code | 21 blank | 91 comment | 12 complexity | 14843b169e3c787ff36a3770e56e071f MD5 | raw file
  1/* ****************************************************************************
  2 *
  3 * Copyright (c) Microsoft Corporation. 
  4 *
  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.
 10 *
 11 * You must not remove this notice, or any other, from this software.
 12 *
 13 *
 14 * ***************************************************************************/
 15
 16using System;
 17using System.Collections.Generic;
 18using System.Collections.ObjectModel;
 19using System.Diagnostics;
 20using System.Dynamic.Utils;
 21using System.Reflection;
 22
 23#if !FEATURE_CORE_DLR
 24namespace Microsoft.Scripting.Ast {
 25#else
 26namespace System.Linq.Expressions {
 27#endif
 28    /// <summary>
 29    /// Represents an expression that applies a delegate or lambda expression to a list of argument expressions.
 30    /// </summary>
 31    [DebuggerTypeProxy(typeof(Expression.InvocationExpressionProxy))]
 32    public sealed class InvocationExpression : Expression, IArgumentProvider {
 33        private IList<Expression> _arguments;
 34        private readonly Expression _lambda;
 35        private readonly Type _returnType;
 36
 37        internal InvocationExpression(Expression lambda, IList<Expression> arguments, Type returnType) {
 38            _lambda = lambda;
 39            _arguments = arguments;
 40            _returnType = returnType;
 41        }
 42
 43        /// <summary>
 44        /// Gets the static type of the expression that this <see cref="Expression" /> represents.
 45        /// </summary>
 46        /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
 47        public sealed override Type Type {
 48            get { return _returnType; }
 49        }
 50
 51        /// <summary>
 52        /// Returns the node type of this Expression. Extension nodes should return
 53        /// ExpressionType.Extension when overriding this method.
 54        /// </summary>
 55        /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
 56        public sealed override ExpressionType NodeType {
 57            get { return ExpressionType.Invoke; }
 58        }
 59
 60        /// <summary>
 61        /// Gets the delegate or lambda expression to be applied.
 62        /// </summary>
 63        public Expression Expression {
 64            get { return _lambda; }
 65        }
 66
 67        /// <summary>
 68        /// Gets the arguments that the delegate or lambda expression is applied to.
 69        /// </summary>
 70        public ReadOnlyCollection<Expression> Arguments {
 71            get { return ReturnReadOnly(ref _arguments); }
 72        }
 73
 74        /// <summary>
 75        /// Creates a new expression that is like this one, but using the
 76        /// supplied children. If all of the children are the same, it will
 77        /// return this expression.
 78        /// </summary>
 79        /// <param name="expression">The <see cref="Expression" /> property of the result.</param>
 80        /// <param name="arguments">The <see cref="Arguments" /> property of the result.</param>
 81        /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
 82        public InvocationExpression Update(Expression expression, IEnumerable<Expression> arguments) {
 83            if (expression == Expression && arguments == Arguments) {
 84                return this;
 85            }
 86
 87            return Expression.Invoke(expression, arguments);
 88        }
 89
 90        Expression IArgumentProvider.GetArgument(int index) {
 91            return _arguments[index];
 92        }
 93
 94        int IArgumentProvider.ArgumentCount {
 95            get {
 96                return _arguments.Count;
 97            }
 98        }
 99
100        /// <summary>
101        /// Dispatches to the specific visit method for this node type.
102        /// </summary>
103        protected internal override Expression Accept(ExpressionVisitor visitor) {
104            return visitor.VisitInvocation(this);
105        }
106
107        internal InvocationExpression Rewrite(Expression lambda, Expression[] arguments) {
108            Debug.Assert(lambda != null);
109            Debug.Assert(arguments == null || arguments.Length == _arguments.Count);
110
111            return Expression.Invoke(lambda, arguments ?? _arguments);
112        }
113
114        internal LambdaExpression LambdaOperand {
115            get {
116                return (_lambda.NodeType == ExpressionType.Quote)
117                    ? (LambdaExpression)((UnaryExpression)_lambda).Operand
118                    : (_lambda as LambdaExpression);
119            }
120        }
121    }
122
123    public partial class Expression {
124
125        ///<summary>
126        ///Creates an <see cref="T:System.Linq.Expressions.InvocationExpression" /> that 
127        ///applies a delegate or lambda expression to a list of argument expressions.
128        ///</summary>
129        ///<returns>
130        ///An <see cref="T:System.Linq.Expressions.InvocationExpression" /> that 
131        ///applies the specified delegate or lambda expression to the provided arguments.
132        ///</returns>
133        ///<param name="expression">
134        ///An <see cref="T:System.Linq.Expressions.Expression" /> that represents the delegate
135        ///or lambda expression to be applied.
136        ///</param>
137        ///<param name="arguments">
138        ///An array of <see cref="T:System.Linq.Expressions.Expression" /> objects
139        ///that represent the arguments that the delegate or lambda expression is applied to.
140        ///</param>
141        ///<exception cref="T:System.ArgumentNullException">
142        ///<paramref name="expression" /> is null.</exception>
143        ///<exception cref="T:System.ArgumentException">
144        ///<paramref name="expression" />.Type does not represent a delegate type or an <see cref="T:System.Linq.Expressions.Expression`1" />.-or-The <see cref="P:System.Linq.Expressions.Expression.Type" /> property of an element of <paramref name="arguments" /> is not assignable to the type of the corresponding parameter of the delegate represented by <paramref name="expression" />.</exception>
145        ///<exception cref="T:System.InvalidOperationException">
146        ///<paramref name="arguments" /> does not contain the same number of elements as the list of parameters for the delegate represented by <paramref name="expression" />.</exception>
147        public static InvocationExpression Invoke(Expression expression, params Expression[] arguments) {
148            return Invoke(expression, (IEnumerable<Expression>)arguments);
149        }
150
151        ///<summary>
152        ///Creates an <see cref="T:System.Linq.Expressions.InvocationExpression" /> that 
153        ///applies a delegate or lambda expression to a list of argument expressions.
154        ///</summary>
155        ///<returns>
156        ///An <see cref="T:System.Linq.Expressions.InvocationExpression" /> that 
157        ///applies the specified delegate or lambda expression to the provided arguments.
158        ///</returns>
159        ///<param name="expression">
160        ///An <see cref="T:System.Linq.Expressions.Expression" /> that represents the delegate
161        ///or lambda expression to be applied.
162        ///</param>
163        ///<param name="arguments">
164        ///An <see cref="T:System.Collections.Generic.IEnumerable`1" /> of <see cref="T:System.Linq.Expressions.Expression" /> objects
165        ///that represent the arguments that the delegate or lambda expression is applied to.
166        ///</param>
167        ///<exception cref="T:System.ArgumentNullException">
168        ///<paramref name="expression" /> is null.</exception>
169        ///<exception cref="T:System.ArgumentException">
170        ///<paramref name="expression" />.Type does not represent a delegate type or an <see cref="T:System.Linq.Expressions.Expression`1" />.-or-The <see cref="P:System.Linq.Expressions.Expression.Type" /> property of an element of <paramref name="arguments" /> is not assignable to the type of the corresponding parameter of the delegate represented by <paramref name="expression" />.</exception>
171        ///<exception cref="T:System.InvalidOperationException">
172        ///<paramref name="arguments" /> does not contain the same number of elements as the list of parameters for the delegate represented by <paramref name="expression" />.</exception>
173        public static InvocationExpression Invoke(Expression expression, IEnumerable<Expression> arguments) {
174            RequiresCanRead(expression, "expression");
175
176            var args = arguments.ToReadOnly();
177            var mi = GetInvokeMethod(expression);
178            ValidateArgumentTypes(mi, ExpressionType.Invoke, ref args);
179            return new InvocationExpression(expression, args, mi.ReturnType);
180        }
181
182        /// <summary>
183        /// Gets the delegate's Invoke method; used by InvocationExpression.
184        /// </summary>
185        /// <param name="expression">The expression to be invoked.</param>
186        internal static MethodInfo GetInvokeMethod(Expression expression) {
187            Type delegateType = expression.Type;
188            if (!expression.Type.IsSubclassOf(typeof(MulticastDelegate))) {
189                Type exprType = TypeUtils.FindGenericType(typeof(Expression<>), expression.Type);
190                if (exprType == null) {
191                    throw Error.ExpressionTypeNotInvocable(expression.Type);
192                }
193                delegateType = exprType.GetGenericArguments()[0];
194            }
195
196            return delegateType.GetMethod("Invoke");
197        }
198    }
199}