/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/InvocationExpression.cs
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}