PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

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

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