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

/Languages/Ruby/Ruby/Runtime/Calls/BlockDispatcherUnsplatN.cs

http://github.com/IronLanguages/main
C# | 168 lines | 108 code | 28 blank | 32 comment | 20 complexity | cdc186fd40ff7256eb27dad4db4cda2a MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  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. * ironruby@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.Text;
  18. using Microsoft.Scripting.Utils;
  19. using System.Diagnostics;
  20. using IronRuby.Builtins;
  21. using System.Collections;
  22. namespace IronRuby.Runtime.Calls {
  23. using BlockCallTargetUnsplatN = Func<BlockParam, object, object[], RubyArray, object>;
  24. // L(n, *)
  25. internal sealed class BlockDispatcherUnsplatN : BlockDispatcherN<BlockCallTargetUnsplatN> {
  26. internal BlockDispatcherUnsplatN(int parameterCount, BlockSignatureAttributes attributesAndArity, string sourcePath, int sourceLine)
  27. : base(parameterCount, attributesAndArity, sourcePath, sourceLine) {
  28. Debug.Assert(HasUnsplatParameter);
  29. }
  30. // R(0, -)
  31. public override object Invoke(BlockParam/*!*/ param, object self, Proc procArg) {
  32. return InvokeInternal(param, self, procArg, ArrayUtils.EmptyObjects);
  33. }
  34. // R(1, -)
  35. public override object InvokeNoAutoSplat(BlockParam/*!*/ param, object self, Proc procArg, object arg1) {
  36. return InvokeInternal(param, self, procArg, new object[] { arg1 }); // TODO: optimize
  37. }
  38. // R(1, -)
  39. public override object Invoke(BlockParam/*!*/ param, object self, Proc procArg, object arg1) {
  40. if (_parameterCount > 0) {
  41. IList list = arg1 as IList ?? Protocols.ImplicitTrySplat(param.RubyContext, arg1) ?? new object[] { arg1 }; // TODO: optimize
  42. return InvokeSplatInternal(param, self, procArg, ArrayUtils.EmptyObjects, list);
  43. } else {
  44. return InvokeInternal(param, self, procArg, new object[] { arg1 }); // TODO: optimize
  45. }
  46. }
  47. // R(2, -)
  48. public override object Invoke(BlockParam/*!*/ param, object self, Proc procArg, object arg1, object arg2) {
  49. return InvokeInternal(param, self, procArg, new object[] { arg1, arg2 });// TODO: optimize
  50. }
  51. // R(3, -)
  52. public override object Invoke(BlockParam/*!*/ param, object self, Proc procArg, object arg1, object arg2, object arg3) {
  53. return InvokeInternal(param, self, procArg, new object[] { arg1, arg2, arg3 });// TODO: optimize
  54. }
  55. // R(4, -)
  56. public override object Invoke(BlockParam/*!*/ param, object self, Proc procArg, object arg1, object arg2, object arg3, object arg4) {
  57. return InvokeInternal(param, self, procArg, new object[] { arg1, arg2, arg3, arg4 });// TODO: optimize
  58. }
  59. // R(N, -)
  60. public override object Invoke(BlockParam/*!*/ param, object self, Proc procArg, object[]/*!*/ args) {
  61. return InvokeInternal(param, self, procArg, args);
  62. }
  63. private object InvokeInternal(BlockParam/*!*/ param, object self, Proc procArg, object[]/*!*/ args) {
  64. // TODO: optimize
  65. if (args.Length < _parameterCount) {
  66. Array.Resize(ref args, _parameterCount);
  67. return _block(param, self, args, RubyOps.MakeArray0());
  68. } else if (args.Length == _parameterCount) {
  69. return _block(param, self, args, RubyOps.MakeArray0());
  70. } else if (_parameterCount == 0) {
  71. return _block(param, self, ArrayUtils.EmptyObjects, RubyOps.MakeArrayN(args));
  72. } else {
  73. var actualArgs = new object[_parameterCount];
  74. for (int i = 0; i < actualArgs.Length; i++) {
  75. actualArgs[i] = args[i];
  76. }
  77. var array = new RubyArray(args.Length - _parameterCount);
  78. for (int i = _parameterCount; i < args.Length; i++) {
  79. array.Add(args[i]);
  80. }
  81. return _block(param, self, actualArgs, array);
  82. }
  83. }
  84. // R(0, *)
  85. public override object InvokeSplat(BlockParam/*!*/ param, object self, Proc procArg, IList/*!*/ splattee) {
  86. if (splattee.Count == 1) {
  87. return Invoke(param, self, procArg, splattee[0]);
  88. } else {
  89. return InvokeSplatInternal(param, self, procArg, ArrayUtils.EmptyObjects, splattee);
  90. }
  91. }
  92. // R(1, *)
  93. public override object InvokeSplat(BlockParam/*!*/ param, object self, Proc procArg, object arg1, IList/*!*/ splattee) {
  94. if (splattee.Count == 0) {
  95. return Invoke(param, self, procArg, arg1);
  96. } else {
  97. return InvokeSplatInternal(param, self, procArg, new object[] { arg1 }, splattee);
  98. }
  99. }
  100. // R(2, *)
  101. public override object InvokeSplat(BlockParam/*!*/ param, object self, Proc procArg, object arg1, object arg2, IList/*!*/ splattee) {
  102. return InvokeSplatInternal(param, self, procArg, new object[] { arg1, arg2 }, splattee);
  103. }
  104. // R(3, *)
  105. public override object InvokeSplat(BlockParam/*!*/ param, object self, Proc procArg, object arg1, object arg2, object arg3, IList/*!*/ splattee) {
  106. return InvokeSplatInternal(param, self, procArg, new object[] { arg1, arg2, arg3 }, splattee);
  107. }
  108. // R(4, *)
  109. public override object InvokeSplat(BlockParam/*!*/ param, object self, Proc procArg, object arg1, object arg2, object arg3, object arg4, IList/*!*/ splattee) {
  110. return InvokeSplatInternal(param, self, procArg, new object[] { arg1, arg2, arg3, arg4 }, splattee);
  111. }
  112. // R(N, *)
  113. public override object InvokeSplat(BlockParam/*!*/ param, object self, Proc procArg, object[]/*!*/ args, IList/*!*/ splattee) {
  114. return InvokeSplatInternal(param, self, procArg, args, splattee);
  115. }
  116. // R(N, *, =)
  117. public override object InvokeSplatRhs(BlockParam/*!*/ param, object self, Proc procArg, object[]/*!*/ args, IList/*!*/ splattee, object rhs) {
  118. var list = new RubyArray(splattee.Count + 1);
  119. list.AddRange(splattee);
  120. list.Add(rhs);
  121. splattee = list;
  122. return InvokeSplatInternal(param, self, procArg, args, list);
  123. }
  124. private object InvokeSplatInternal(BlockParam/*!*/ param, object self, Proc procArg, object[]/*!*/ args, IList/*!*/ splattee) {
  125. int argsLength = args.Length;
  126. int nextArg, nextItem;
  127. CreateArgumentsFromSplattee(_parameterCount, out nextArg, out nextItem, ref args, splattee);
  128. var array = new RubyArray();
  129. // remaining args:
  130. while (nextArg < argsLength) {
  131. array.Add(args[nextArg++]);
  132. }
  133. // remaining items:
  134. while (nextItem < splattee.Count) {
  135. array.Add(splattee[nextItem++]);
  136. }
  137. return _block(param, self, args, array);
  138. }
  139. }
  140. }