PageRenderTime 52ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Microsoft.Scripting/Actions/Calls/ParamsArgBuilder.cs

https://bitbucket.org/stefanrusek/xronos
C# | 127 lines | 95 code | 18 blank | 14 comment | 10 complexity | 764964039b4a2709eec2e7ea3f8accc3 MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. 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 Microsoft Public License, 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 Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. #if CODEPLEX_40
  16. using System;
  17. #else
  18. using System; using Microsoft;
  19. #endif
  20. using System.Collections.Generic;
  21. #if CODEPLEX_40
  22. using System.Dynamic;
  23. using System.Linq.Expressions;
  24. #else
  25. using Microsoft.Scripting;
  26. using Microsoft.Linq.Expressions;
  27. #endif
  28. using System.Reflection;
  29. using Microsoft.Scripting.Utils;
  30. namespace Microsoft.Scripting.Actions.Calls {
  31. #if CODEPLEX_40
  32. using Ast = System.Linq.Expressions.Expression;
  33. #else
  34. using Ast = Microsoft.Linq.Expressions.Expression;
  35. #endif
  36. internal sealed class ParamsArgBuilder : ArgBuilder {
  37. private readonly int _start;
  38. private readonly int _count;
  39. private readonly Type _elementType;
  40. public ParamsArgBuilder(ParameterInfo info, Type elementType, int start, int count)
  41. : base(info) {
  42. ContractUtils.RequiresNotNull(elementType, "elementType");
  43. ContractUtils.Requires(start >= 0, "start");
  44. ContractUtils.Requires(count >= 0, "count");
  45. _start = start;
  46. _count = count;
  47. _elementType = elementType;
  48. }
  49. public override int Priority {
  50. get { return 4; }
  51. }
  52. internal protected override Expression ToExpression(ParameterBinder parameterBinder, IList<Expression> parameters, bool[] hasBeenUsed) {
  53. List<Expression> elems = new List<Expression>(_count);
  54. for (int i = _start; i < _start + _count; i++) {
  55. if (!hasBeenUsed[i]) {
  56. elems.Add(parameterBinder.ConvertExpression(parameters[i], ParameterInfo, _elementType));
  57. hasBeenUsed[i] = true;
  58. }
  59. }
  60. return Ast.NewArrayInit(_elementType, elems);
  61. }
  62. protected internal override Func<object[], object> ToDelegate(ParameterBinder parameterBinder, IList<DynamicMetaObject> knownTypes, bool[] hasBeenUsed) {
  63. List<Func<object[], object>> indexes = new List<Func<object[], object>>(_count);
  64. for (int i = _start; i < _start + _count; i++) {
  65. if (!hasBeenUsed[i]) {
  66. indexes.Add(parameterBinder.ConvertObject(i + 1, knownTypes[i], ParameterInfo, _elementType));
  67. hasBeenUsed[i] = true;
  68. }
  69. }
  70. if (_elementType == typeof(object)) {
  71. return new ParamArrayDelegate<object>(indexes.ToArray(), _start).MakeParamsArray;
  72. }
  73. Type genType = typeof(ParamArrayDelegate<>).MakeGenericType(_elementType);
  74. return (Func<object[], object>)Delegate.CreateDelegate(
  75. typeof(Func<object[], object>),
  76. Activator.CreateInstance(genType, indexes.ToArray(), _start),
  77. genType.GetMethod("MakeParamsArray"));
  78. }
  79. class ParamArrayDelegate<T> {
  80. private readonly Func<object[], object>[] _indexes;
  81. private readonly int _start;
  82. public ParamArrayDelegate(Func<object[], object>[] indexes, int start) {
  83. _indexes = indexes;
  84. _start = start;
  85. }
  86. public T[] MakeParamsArray(object[] args) {
  87. T[] res = new T[_indexes.Length];
  88. for (int i = 0; i < _indexes.Length; i++) {
  89. if (_indexes[i] == null) {
  90. res[i] = (T)args[_start + i + 1];
  91. } else {
  92. res[i] = (T)_indexes[i](args);
  93. }
  94. }
  95. return res;
  96. }
  97. }
  98. internal override bool CanGenerateDelegate {
  99. get {
  100. return true;
  101. }
  102. }
  103. public override Type Type {
  104. get {
  105. return _elementType.MakeArrayType();
  106. }
  107. }
  108. }
  109. }