PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/Microsoft.Scripting/Actions/Calls/ParamsDictArgBuilder.cs

https://bitbucket.org/stefanrusek/xronos
C# | 130 lines | 97 code | 15 blank | 18 comment | 6 complexity | c22d7a0ff8d2dcd07a588a6132c6152a 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.Runtime;
  30. using AstUtils = Microsoft.Scripting.Ast.Utils;
  31. namespace Microsoft.Scripting.Actions.Calls {
  32. #if CODEPLEX_40
  33. using Ast = System.Linq.Expressions.Expression;
  34. #else
  35. using Ast = Microsoft.Linq.Expressions.Expression;
  36. #endif
  37. using Microsoft.Scripting.Utils;
  38. /// <summary>
  39. /// Builds the parameter for a params dictionary argument - this collects all the extra name/value
  40. /// pairs provided to the function into a SymbolDictionary which is passed to the function.
  41. /// </summary>
  42. internal sealed class ParamsDictArgBuilder : ArgBuilder {
  43. private readonly string[] _names;
  44. private readonly int[] _nameIndexes;
  45. private readonly int _argIndex;
  46. public ParamsDictArgBuilder(ParameterInfo info, int argIndex, string[] names, int[] nameIndexes)
  47. : base(info) {
  48. Assert.NotNull(names, nameIndexes);
  49. _argIndex = argIndex;
  50. _names = names;
  51. _nameIndexes = nameIndexes;
  52. }
  53. public override int Priority {
  54. get { return 3; }
  55. }
  56. internal protected override Expression ToExpression(ParameterBinder parameterBinder, IList<Expression> parameters, bool[] hasBeenUsed) {
  57. Expression res = Ast.Call(
  58. typeof(BinderOps).GetMethod("MakeSymbolDictionary"),
  59. Ast.NewArrayInit(typeof(string), ConstantNames()),
  60. AstUtils.NewArrayHelper(typeof(object), GetParameters(parameters, hasBeenUsed))
  61. );
  62. return res;
  63. }
  64. public override Type Type {
  65. get {
  66. return typeof(IAttributesCollection);
  67. }
  68. }
  69. private List<Expression> GetParameters(IList<Expression> parameters, bool[] hasBeenUsed) {
  70. List<Expression> res = new List<Expression>(_nameIndexes.Length);
  71. for (int i = 0; i < _nameIndexes.Length; i++) {
  72. int parameterIndex = _nameIndexes[i] + _argIndex;
  73. if (!hasBeenUsed[parameterIndex]) {
  74. res.Add(parameters[parameterIndex]);
  75. hasBeenUsed[parameterIndex] = true;
  76. }
  77. }
  78. return res;
  79. }
  80. private int[] GetParameters(bool[] hasBeenUsed) {
  81. var res = new List<int>(_nameIndexes.Length);
  82. for (int i = 0; i < _nameIndexes.Length; i++) {
  83. int parameterIndex = _nameIndexes[i] + _argIndex;
  84. if (!hasBeenUsed[parameterIndex]) {
  85. res.Add(parameterIndex);
  86. hasBeenUsed[parameterIndex] = true;
  87. }
  88. }
  89. return res.ToArray();
  90. }
  91. private Expression[] ConstantNames() {
  92. Expression[] res = new Expression[_names.Length];
  93. for (int i = 0; i < _names.Length; i++) {
  94. res[i] = AstUtils.Constant(_names[i]);
  95. }
  96. return res;
  97. }
  98. internal override bool CanGenerateDelegate {
  99. get {
  100. return true;
  101. }
  102. }
  103. protected internal override Func<object[], object> ToDelegate(ParameterBinder parameterBinder, IList<DynamicMetaObject> knownTypes, bool[] hasBeenUsed) {
  104. string[] names = _names;
  105. int[] indexes = GetParameters(hasBeenUsed);
  106. return (args) => {
  107. object[] values = new object[indexes.Length];
  108. for (int i = 0; i < indexes.Length; i++) {
  109. values[i] = args[indexes[i] + 1];
  110. }
  111. return BinderOps.MakeSymbolDictionary(names, values);
  112. };
  113. }
  114. }
  115. }