PageRenderTime 61ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/Languages/Ruby/IronRuby.Tests/Runtime/ClrTests.cs

http://github.com/IronLanguages/main
C# | 3557 lines | 2955 code | 425 blank | 177 comment | 58 complexity | 014209dbc0be4dec9eb1e47ef9acca39 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full 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. * 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;
  17. using System.Collections.Generic;
  18. using System.Diagnostics;
  19. using System.Linq.Expressions;
  20. using System.Reflection;
  21. using System.Runtime.CompilerServices;
  22. using System.Runtime.InteropServices;
  23. using IronRuby.Builtins;
  24. using IronRuby.Runtime;
  25. using Microsoft.Scripting.Hosting;
  26. using Microsoft.Scripting.Math;
  27. using Microsoft.Scripting.Runtime;
  28. using Microsoft.Scripting.Utils;
  29. #if !CLR2
  30. using BigInt = System.Numerics.BigInteger;
  31. using System.Reflection.Emit;
  32. #endif
  33. namespace IronRuby.Tests {
  34. public partial class Tests {
  35. public readonly string FuncFullName = typeof(Func<>).FullName.Split('`')[0].Replace(".", "::");
  36. public readonly string ActionFullName = typeof(Action).FullName.Split('`')[0].Replace(".", "::");
  37. #region Members: Fields, Methods, Properties, Indexers
  38. public class ClassWithFields {
  39. public int Field = 1;
  40. public readonly int RoField = 2;
  41. public static int StaticField = 3;
  42. public const int ConstField = 4;
  43. }
  44. public void ClrFields1() {
  45. Context.DefineGlobalVariable("obj", new ClassWithFields());
  46. AssertOutput(delegate() {
  47. CompilerTest(@"
  48. C = $obj.class
  49. puts $obj.field
  50. puts $obj.RoField
  51. $obj.field = 10
  52. puts $obj.field
  53. ($obj.RoField = 20) rescue puts $!.class
  54. puts C.static_field
  55. puts C.const_field
  56. C.static_field = 30
  57. puts C.static_field
  58. (C.const_field = 40) rescue puts $!.class
  59. ");
  60. }, @"
  61. 1
  62. 2
  63. 10
  64. NoMethodError
  65. 3
  66. 4
  67. 30
  68. NoMethodError
  69. ");
  70. }
  71. public class ClassWithField1 {
  72. public int F = 1;
  73. }
  74. public class ClassWithField2 : ClassWithField1 {
  75. public new static int F = 2;
  76. }
  77. public void ClrFields2() {
  78. Context.DefineGlobalVariable("obj", new ClassWithField2());
  79. AssertOutput(delegate() {
  80. CompilerTest(@"
  81. puts $obj.class.F
  82. puts $obj.F
  83. ");
  84. }, @"
  85. 2
  86. 1
  87. ");
  88. }
  89. public class ClassWithMethods1 {
  90. public int RoProperty { get { return 3; } }
  91. public int RwProperty { get { return 4; } set { } }
  92. public int WoProperty { set { } }
  93. public int M() { return 1; }
  94. public static int StaticMethod() { return 2; }
  95. }
  96. public void ClrMethods1() {
  97. Context.DefineGlobalVariable("obj", new ClassWithMethods1());
  98. Context.DefineGlobalVariable("cls", typeof(ClassWithMethods1));
  99. AssertOutput(delegate() {
  100. CompilerTest(@"
  101. C = $obj.class
  102. puts $obj.m
  103. puts C.static_method
  104. puts $cls.static_methods rescue puts $!.class
  105. ($obj.RoProperty = 10) rescue puts $!.class
  106. $obj.WoProperty = 20
  107. $obj.RwProperty = 30
  108. puts $obj.RoProperty
  109. puts $obj.WoProperty rescue puts $!.class
  110. puts $obj.RwProperty
  111. ");
  112. }, @"
  113. 1
  114. 2
  115. NoMethodError
  116. NoMethodError
  117. 3
  118. NoMethodError
  119. 4
  120. ");
  121. }
  122. /// <summary>
  123. /// Order of initialization of CLR methods.
  124. /// </summary>
  125. public void ClrMethods2() {
  126. Context.ObjectClass.SetConstant("C", Context.GetClass(typeof(ClassWithMethods1)));
  127. XTestOutput(@"
  128. class C
  129. def m; 2; end # replace CLR method with Ruby method before we use the CLR one
  130. remove_method :m # remove Ruby method
  131. new.m rescue p $! # we shouldn't call the CLR method
  132. end
  133. ", @"
  134. ");
  135. }
  136. public class ClassWithEquals1 {
  137. // define overload of Equals so that we get a method group with mixed instance and static methods inherited from Object's method group
  138. public static bool Equals(object o1, object o2, object o3) { return o1.Equals(o2); }
  139. }
  140. /// <summary>
  141. /// Mixing instance and static methods - instance Object::Equals(Object), static Object::Equals(Object, Object).
  142. /// </summary>
  143. public void ClrMethods3() {
  144. Context.ObjectClass.SetConstant("C", Context.GetClass(typeof(ClassWithEquals1)));
  145. TestOutput(@"
  146. puts 1.Equals(2) # instance
  147. puts 1.Equals(2,3) rescue p $! # static invoked with instance
  148. puts C.Equals(C) # instance invoked on a class (statically)
  149. puts C.Equals(3,3) # static
  150. puts C.Equals(3,3,4) # overload
  151. ", @"
  152. false
  153. #<ArgumentError: wrong number of arguments (2 for 1)>
  154. true
  155. true
  156. true
  157. ");
  158. }
  159. /// <summary>
  160. /// Builtin types only expose CLR methods under unmangled names (mangling is no applied).
  161. /// </summary>
  162. public void ClrMethods4() {
  163. TestOutput(@"
  164. a = Exception.new
  165. p a.method(:data) rescue p $!
  166. p a.method(:Data)
  167. ", @"
  168. #<NameError: undefined method `data' for class `Exception'>
  169. #<Method: Exception#Data>
  170. ");
  171. }
  172. public void ClrMembers1() {
  173. TestOutput(@"
  174. a = [1,2,3]
  175. p m = a.clr_member(:count)
  176. p m[]
  177. p m = a.clr_member(:index_of)
  178. p m.clr_members.size
  179. p m.overload(Object).clr_members
  180. ", @"
  181. #<Method: Array#count>
  182. 3
  183. #<Method: Array#index_of>
  184. 3
  185. [Int32 IndexOf(System.Object)]
  186. ");
  187. TestOutput(@"
  188. class C < Array
  189. end
  190. p C.new.clr_member(:index_of).call(1)
  191. ", @"
  192. -1
  193. ");
  194. }
  195. public class ClassWithIndexer1 {
  196. public int[,] Values = new int[,] { { 0, 10 }, { 20, 30 } };
  197. public int this[int i, int j] { get { return Values[i, j]; } set { Values[i, j] = value; } }
  198. }
  199. public void ClrIndexers1() {
  200. Context.ObjectClass.SetConstant("CI", Context.GetClass(typeof(ClassWithIndexer1)));
  201. // default indexers:
  202. AssertOutput(() => CompilerTest(@"
  203. c = CI.new
  204. c[0,1] += 1
  205. p c[0, 1]
  206. "), @"
  207. 11
  208. ");
  209. // non-default indexers:
  210. // TODO: We need to use VB or generate IL to test this.
  211. // TODO: improve access
  212. // If a property accessor with parameters is called without arguments the result is a PropertyAccessor object with [], []= defined.
  213. // Then the calls could look like c.foo[1,2] = 3.
  214. // AssertOutput(() => CompilerTest(@"
  215. //c = CI.new
  216. //c.method(:foo=).call(1, 0, c.method(:foo).call(1, 0) + 5)
  217. //p c.method(:foo).call(1, 0)
  218. //"), @"
  219. //25
  220. //");
  221. }
  222. #endregion
  223. #region Visibility
  224. public class ProtectedA {
  225. protected string Foo(int a) { return "Foo(I): " + a; }
  226. public string Bar(int a) { return "Bar(I): " + a; }
  227. protected string PG<T>(T a) { return "PG<T>(T)"; }
  228. }
  229. public class ProtectedB : ProtectedA {
  230. public string Foo(object a) { return "Foo(O): " + a.ToString(); }
  231. internal protected string Bar(object a) { return "Bar(O): " + a; }
  232. protected int Prop1 { get; set; }
  233. public int Prop2 { get; internal protected set; }
  234. private string Baz(int a) { return "Baz(I): " + a; }
  235. public string Baz(object a) { return "Baz(O): " + a; }
  236. protected static string StaticM() { return "StaticM"; }
  237. protected static string StaticGenericM<T>(T f) { return "StaticGenericM: " + f.ToString(); }
  238. internal protected string PG<T>(T a, int b) { return "PG<T>(T,int)"; }
  239. // TODO:
  240. // protected int Fld;
  241. // protected static int Fld;
  242. // protected event Func<object> Evnt;
  243. }
  244. public void ClrVisibility1() {
  245. Debug.Assert(!Engine.Runtime.Setup.PrivateBinding);
  246. Context.ObjectClass.SetConstant("A", Context.GetClass(typeof(ProtectedA)));
  247. Context.ObjectClass.SetConstant("B", Context.GetClass(typeof(ProtectedB)));
  248. // methods:
  249. AssertOutput(delegate() {
  250. CompilerTest(@"
  251. class C < B; end
  252. a, b, c = A.new, B.new, C.new
  253. puts c.foo(1)
  254. puts b.foo(2)
  255. puts b.bar(22)
  256. a.foo(3) rescue p $!
  257. class A
  258. def foo; 4; end
  259. def bar; 5; end
  260. end
  261. puts c.foo(6)
  262. b.bar(7) rescue p $!
  263. B.StaticM rescue p $!
  264. puts C.StaticM
  265. puts C.method(:StaticGenericM).of(Fixnum)[123]
  266. ");
  267. }, @"
  268. Foo(I): 1
  269. Foo(O): 2
  270. Bar(I): 22
  271. #<NoMethodError: CLR protected method `foo' called for *ProtectedA*>
  272. Foo(O): 6
  273. #<NoMethodError: CLR protected method `bar' called for *ProtectedB*>
  274. #<NoMethodError: CLR protected method `StaticM' called for *ProtectedB*>
  275. StaticM
  276. StaticGenericM: 123
  277. ", OutputFlags.Match);
  278. // generic methods:
  279. TestOutput(@"
  280. class C < B; end
  281. c = C.new
  282. puts c.method(:PG).of(Fixnum).call(1)
  283. puts c.method(:PG).of(Fixnum).call(1,2)
  284. ", @"
  285. PG<T>(T)
  286. PG<T>(T,int)
  287. ");
  288. // properties:
  289. AssertOutput(delegate() {
  290. CompilerTest(@"
  291. class C < B; end
  292. a, b, c = A.new, B.new, C.new
  293. c.prop1 = 1
  294. c.prop2 = 2
  295. puts c.prop1
  296. puts c.prop2
  297. (b.prop2 = 10) rescue p $!
  298. puts b.prop2
  299. ");
  300. }, @"
  301. 1
  302. 2
  303. #<NoMethodError: CLR protected method `prop2=' called for *ProtectedB*>
  304. 0
  305. ", OutputFlags.Match);
  306. }
  307. [Options(PrivateBinding = true)]
  308. public void ClrVisibility2() {
  309. Debug.Assert(Engine.Runtime.Setup.PrivateBinding);
  310. if (_driver.PartialTrust) return;
  311. Context.ObjectClass.SetConstant("A", Context.GetClass(typeof(ProtectedA)));
  312. Context.ObjectClass.SetConstant("B", Context.GetClass(typeof(ProtectedB)));
  313. // methods, properties:
  314. TestOutput(@"
  315. class C < B; end
  316. a, b, c = A.new, B.new, C.new
  317. puts a.foo(3)
  318. class A
  319. def bar; 5; end
  320. end
  321. puts b.bar(7)
  322. puts b.baz(1)
  323. b.prop2 = 10
  324. puts b.prop2
  325. ",
  326. @"
  327. Foo(I): 3
  328. Bar(O): 7
  329. Baz(I): 1
  330. 10
  331. ");
  332. }
  333. public delegate void TestDelegate(string a);
  334. public void SpecialMethods() {
  335. var result = Engine.Execute(@"
  336. System::AppDomain.CurrentDomain.CreateInstance(""mscorlib"", ""System.Object"")
  337. ");
  338. Assert(result is System.Runtime.Remoting.ObjectHandle);
  339. var dm = (DynamicMethod)Engine.Execute(@"
  340. System::Reflection::Emit::DynamicMethod.new(""foo"", 1.GetType(), System::Array[System::Type].new(0))
  341. ");
  342. Assert(dm.ReturnType == typeof(int));
  343. var invoke = typeof(TestDelegate).GetMethod("Invoke");
  344. var d = invoke.CreateDelegate(typeof(Action<string>));
  345. Assert(d is Action<string>);
  346. }
  347. #endregion
  348. #region Member Enumeration
  349. /// <summary>
  350. /// No CLR names should be returned for builtin types and singletons.
  351. /// </summary>
  352. public void ClrMethodEnumeration1() {
  353. // built-ins:
  354. var irModules = new[] { "IronRuby" };
  355. using (Context.ClassHierarchyLocker()) {
  356. Context.ObjectClass.EnumerateConstants((module, name, value) => {
  357. RubyModule m = value as RubyModule;
  358. if (m != null && Array.IndexOf(irModules, m.Name) == -1) {
  359. var s = m.GetOrCreateSingletonClass();
  360. AssertNoClrNames(ModuleOps.GetInstanceMethods(m, true), m.Name);
  361. AssertNoClrNames(ModuleOps.GetPrivateInstanceMethods(m, true), m.Name);
  362. AssertNoClrNames(ModuleOps.GetInstanceMethods(s, true), m.Name);
  363. AssertNoClrNames(ModuleOps.GetPrivateInstanceMethods(s, true), m.Name);
  364. }
  365. return false;
  366. });
  367. }
  368. // singletons:
  369. AssertNoClrNames(Engine.Execute<object>(@"class << self; instance_methods + private_instance_methods; end"), null);
  370. AssertNoClrNames(Engine.Execute<object>(@"class << self; class << self; instance_methods + private_instance_methods; end; end"), null);
  371. AssertNoClrNames(Engine.Execute<object>(@"class << Class; instance_methods + private_instance_methods; end"), null);
  372. }
  373. public void ClrMethodEnumeration2() {
  374. TestOutput(@"
  375. class System::Decimal
  376. instance_methods(false).each do |name|
  377. mangled = '__' + name
  378. alias_method(mangled, name)
  379. private mangled
  380. define_method(name) do |*args|
  381. puts ""method called: #{name}""
  382. send mangled, *args
  383. end
  384. end
  385. end
  386. x, y = System::Decimal.new(1), System::Decimal.new(2)
  387. x + y
  388. x.CompareTo(y)
  389. ", @"
  390. method called: +
  391. method called: compare_to
  392. ");
  393. }
  394. public class ClassWithGeneratedMembers1 : I1 {
  395. private class OK {
  396. }
  397. // C# generates display class, anonymous type, anonymos methods and a static field:
  398. private IEnumerable<int> GetInts() {
  399. var t = new { a = 1, b = 2 };
  400. Func<int> f = () => 1;
  401. yield return f();
  402. yield return t.a;
  403. yield return Field;
  404. }
  405. private static int Field = 3;
  406. int I1.f() { return 0; }
  407. }
  408. [Options(PrivateBinding = true)]
  409. public void ClrMethodEnumeration_InvalidNames1() {
  410. Context.ObjectClass.SetConstant("Foo", Context.GetClass(typeof(ClassWithGeneratedMembers1)));
  411. TestOutput(@"
  412. class Foo
  413. def <=>; end
  414. def <<; end
  415. def &; end
  416. def f?; end
  417. def f!; end
  418. def f=; end
  419. end
  420. puts Foo.constants
  421. puts Foo.singleton_methods(false).sort
  422. puts Foo.instance_methods(false).sort
  423. ", @"
  424. OK
  425. field
  426. field=
  427. &
  428. <<
  429. <=>
  430. f!
  431. f=
  432. f?
  433. get_ints
  434. ");
  435. }
  436. private void AssertNoClrNames(object/*!*/ methods, string moduleName) {
  437. var array = (RubyArray)methods;
  438. int idx = array.FindIndex((name) => name is ClrName);
  439. Assert(idx == -1, moduleName + "::" + (idx == -1 ? null : ((ClrName)array[idx]).ActualName));
  440. }
  441. #endregion
  442. #region Generic Methods
  443. #pragma warning disable 67 // event not used
  444. public class GenericMethods {
  445. public static string M0<T>() {
  446. return "M0<" + typeof(T).Name + ">()";
  447. }
  448. public static string M1() {
  449. return "M1()";
  450. }
  451. public static string M1<T>() {
  452. return "M1<" + typeof(T).Name + ">()";
  453. }
  454. public static string M1<S, T>() {
  455. return "M1<" + typeof(S).Name + ", " + typeof(T).Name + ">()";
  456. }
  457. public static string M1<T>(int foo) {
  458. return "M1<" + typeof(T).Name + ">(Fixnum)";
  459. }
  460. public static string M2(int foo) {
  461. return "M2(Fixnum)";
  462. }
  463. public static string M2<T>(int foo) {
  464. return "M2<" + typeof(T).Name + ">(Fixnum)";
  465. }
  466. public static int Field;
  467. public static object Property { get; set; }
  468. public static event Action<Object> Event;
  469. }
  470. #pragma warning restore
  471. public void ClrGenericMethods1() {
  472. Context.ObjectClass.SetConstant("GM", Context.GetClass(typeof(GenericMethods)));
  473. TestOutput(@"
  474. m = GM.method(:M1)
  475. puts m.call
  476. puts m.of().call
  477. puts m.of(String).call
  478. puts m.of(String, Fixnum).call
  479. puts m.call(1) rescue p $!
  480. puts m.of(String, String, String) rescue p $!
  481. ", @"
  482. M1()
  483. M1()
  484. M1<MutableString>()
  485. M1<MutableString, Int32>()
  486. #<ArgumentError: generic arguments could not be infered for method 'M1'>
  487. #<ArgumentError: wrong number of generic arguments for `M1'>
  488. "
  489. );
  490. TestOutput(@"
  491. m = GM.method(:M2)
  492. puts m.call(1)
  493. puts GM.method(:field).of(Fixnum) rescue p $!
  494. puts GM.method(:property).of(Fixnum) rescue p $!
  495. puts GM.method(:event).of(Fixnum) rescue p $!
  496. ", @"
  497. M2(Fixnum)
  498. #<ArgumentError: wrong number of generic arguments for `field'>
  499. #<ArgumentError: wrong number of generic arguments for `property'>
  500. #<ArgumentError: wrong number of generic arguments for `event'>
  501. "
  502. );
  503. }
  504. public abstract class GenericMethods2 {
  505. public abstract T Foo<T>(T arg);
  506. }
  507. internal class GenericMethods3 : GenericMethods2 {
  508. public override T Foo<T>(T arg) {
  509. return arg;
  510. }
  511. }
  512. public void ClrGenericMethods2() {
  513. Context.ObjectClass.SetConstant("GM3", new GenericMethods3());
  514. TestOutput(@"
  515. puts GM3.foo(123)
  516. ", @"
  517. 123
  518. ");
  519. }
  520. public class Inference1 {
  521. public int ByRef<T>(ref T x) {
  522. x = (T)(object)((int)(object)x + 1);
  523. return 0;
  524. }
  525. public int Array<T>(T[] x) {
  526. return 1;
  527. }
  528. public int Multiple<S, R>(IEnumerable<S> source, Func<S, R> selector) {
  529. return 2;
  530. }
  531. public int DeepShape<T>(Dictionary<Dictionary<T, string>, Dictionary<int, T>> arg) {
  532. return 3;
  533. }
  534. public int Complex<A,B,C>(ref Dictionary<List<Dictionary<Func<A, B[][,,,][], C>[], int>>, Func<Dictionary<int, A>, B, C>>[] arg) {
  535. return 4;
  536. }
  537. public int Where<T>(IEnumerable<T> e, Func<T, bool> f) {
  538. return 5;
  539. }
  540. public int Where<T>(IEnumerable<T> e, Func<T, int, bool> f) {
  541. return 6;
  542. }
  543. public int Where<T>(IEnumerable<T> e, object f) {
  544. return 7;
  545. }
  546. public int Apply<T>(IEnumerable<T> e, Action<T> f) {
  547. return 8;
  548. }
  549. public int Mixed<T>(T arg) {
  550. return 8;
  551. }
  552. public int Mixed(object arg) {
  553. return 9;
  554. }
  555. }
  556. public void ClrGenericParametersInference1() {
  557. Context.ObjectClass.SetConstant("F", Context.GetClass(typeof(Func<object,string>)));
  558. Context.ObjectClass.SetConstant("SB", Context.GetClass(typeof(StrongBox<int>)));
  559. Context.ObjectClass.SetConstant("SBx",
  560. new StrongBox<Dictionary<List<Dictionary<Func<int, bool[][,,,][], double>[], int>>, Func<Dictionary<int, int>, bool, double>>[]>(null)
  561. );
  562. Context.ObjectClass.SetConstant("I", new Inference1());
  563. Context.ObjectClass.SetConstant("E", Context.GetClass(typeof(InteropTests.Generics1.Extensions)));
  564. TestOutput(@"
  565. p I.Array(System::Array[Fixnum].new(3))
  566. p I.Multiple([1,2,3], F.new { |x| x.to_s })
  567. E.Select([1,2], F.new { |x| x.to_s + '!' }).each { |a| puts a }
  568. E.Select([1,2], lambda { |x| x + 1 }).each { |a| puts a }
  569. ", @"
  570. 1
  571. 2
  572. 1!
  573. 2!
  574. 2
  575. 3
  576. ");
  577. TestOutput(@"
  578. p I.ByRef(2)
  579. sb = SB.new(10)
  580. p I.ByRef(sb), sb.Value
  581. ", @"
  582. [0, 3]
  583. 0
  584. 11
  585. ");
  586. TestOutput(@"
  587. include System::Collections::Generic
  588. p I.DeepShape(Dictionary[List[Fixnum], Dictionary[Fixnum, Fixnum]].new) rescue p $!
  589. p I.DeepShape(Dictionary[Dictionary[Fixnum, System::String], Dictionary[Fixnum, Fixnum]].new)
  590. ", @"
  591. #<ArgumentError: generic arguments could not be infered for method 'DeepShape'>
  592. 3
  593. ");
  594. TestOutput(@"
  595. p I.Complex(SBx)
  596. ", @"
  597. 4
  598. ");
  599. TestOutput(@"
  600. l1 = lambda { |x| }
  601. l2 = lambda { |x, y| }
  602. l3 = lambda { |*| }
  603. a = System::Array[Object].new(1)
  604. p I.Where(a, l1)
  605. p I.Where(a, l2)
  606. p I.Where(a, l3) rescue puts 'ambiguous'
  607. p I.Where(a, 123)
  608. ", @"
  609. 5
  610. 6
  611. ambiguous
  612. 7
  613. ");
  614. // TODO:
  615. // XTestOutput(@"
  616. //a = System::Array[Fixnum].new(1)
  617. //p I.Apply(a, lambda { |x| })
  618. //", @"
  619. //5
  620. //");
  621. // an inferred type is more specific than object:
  622. TestOutput(@"
  623. p I.Mixed(1)
  624. ", @"
  625. 8
  626. ");
  627. }
  628. #endregion
  629. #region Extension Methods
  630. public void ClrExtensionMethods0() {
  631. bool expectExact = typeof(Enumerable).Assembly.FullName == "System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
  632. Dictionary<string, int> expected = new Dictionary<string, int>();
  633. foreach (string name in new[] {
  634. "AsQueryable", "AsQueryable", "Where", "Where", "OfType", "Cast", "Select", "Select", "SelectMany", "SelectMany", "SelectMany", "SelectMany", "Join", "Join", "GroupJoin",
  635. "GroupJoin", "OrderBy", "OrderBy", "OrderByDescending", "OrderByDescending", "ThenBy", "ThenBy", "ThenByDescending", "ThenByDescending", "Take", "TakeWhile",
  636. "TakeWhile", "Skip", "SkipWhile", "SkipWhile", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "Distinct", "Distinct",
  637. "Concat", "Zip", "Union", "Union", "Intersect", "Intersect", "Except", "Except", "First", "First", "FirstOrDefault", "FirstOrDefault", "Last", "Last",
  638. "LastOrDefault", "LastOrDefault", "Single", "Single", "SingleOrDefault", "SingleOrDefault", "ElementAt", "ElementAtOrDefault", "DefaultIfEmpty", "DefaultIfEmpty",
  639. "Contains", "Contains", "Reverse", "SequenceEqual", "SequenceEqual", "Any", "Any", "All", "Count", "Count", "LongCount", "LongCount", "Min", "Min", "Max", "Max",
  640. "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Average", "Average",
  641. "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average",
  642. "Average", "Average", "Average", "Aggregate", "Aggregate", "Aggregate", "Where", "Where", "Select", "Select", "SelectMany", "SelectMany", "SelectMany", "SelectMany",
  643. "Take", "TakeWhile", "TakeWhile", "Skip", "SkipWhile", "SkipWhile", "Join", "Join", "GroupJoin", "GroupJoin", "OrderBy", "OrderBy", "OrderByDescending",
  644. "OrderByDescending", "ThenBy", "ThenBy", "ThenByDescending", "ThenByDescending", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy",
  645. "GroupBy", "Concat", "Zip", "Distinct", "Distinct", "Union", "Union", "Intersect", "Intersect", "Except", "Except", "Reverse", "SequenceEqual", "SequenceEqual",
  646. "AsEnumerable", "ToArray", "ToList", "ToDictionary", "ToDictionary", "ToDictionary", "ToDictionary", "ToLookup", "ToLookup", "ToLookup", "ToLookup", "DefaultIfEmpty",
  647. "DefaultIfEmpty", "OfType", "Cast", "First", "First", "FirstOrDefault", "FirstOrDefault", "Last", "Last", "LastOrDefault", "LastOrDefault", "Single", "Single",
  648. "SingleOrDefault", "SingleOrDefault", "ElementAt", "ElementAtOrDefault", "Any", "Any", "All", "Count", "Count", "LongCount", "LongCount", "Contains", "Contains",
  649. "Aggregate", "Aggregate", "Aggregate", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum",
  650. "Sum", "Sum", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min",
  651. "Min", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max",
  652. "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average",
  653. "Average", "Average", "Average", "Average", "Average", "AsParallel", "AsParallel", "AsOrdered", "AsOrdered", "AsUnordered", "AsParallel", "AsSequential",
  654. "WithDegreeOfParallelism", "WithCancellation", "WithExecutionMode", "WithMergeOptions", "ForAll", "Where", "Where", "Select", "Select", "Zip", "Zip", "Join", "Join",
  655. "Join", "Join", "GroupJoin", "GroupJoin", "GroupJoin", "GroupJoin", "SelectMany", "SelectMany", "SelectMany", "SelectMany", "OrderBy", "OrderBy", "OrderByDescending",
  656. "OrderByDescending", "ThenBy", "ThenBy", "ThenByDescending", "ThenByDescending", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy",
  657. "Aggregate", "Aggregate", "Aggregate", "Aggregate", "Aggregate", "Count", "Count", "LongCount", "LongCount", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum",
  658. "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min",
  659. "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max",
  660. "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average",
  661. "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Any", "Any", "All", "Contains", "Contains", "Take",
  662. "TakeWhile", "TakeWhile", "Skip", "SkipWhile", "SkipWhile", "Concat", "Concat", "SequenceEqual", "SequenceEqual", "SequenceEqual", "SequenceEqual", "Distinct",
  663. "Distinct", "Union", "Union", "Union", "Union", "Intersect", "Intersect", "Intersect", "Intersect", "Except", "Except", "Except", "Except", "AsEnumerable", "ToArray",
  664. "ToList", "ToDictionary", "ToDictionary", "ToDictionary", "ToDictionary", "ToLookup", "ToLookup", "ToLookup", "ToLookup", "Reverse", "OfType", "Cast", "First", "First",
  665. "FirstOrDefault", "FirstOrDefault", "Last", "Last", "LastOrDefault", "LastOrDefault", "Single", "Single", "SingleOrDefault", "SingleOrDefault", "DefaultIfEmpty",
  666. "DefaultIfEmpty", "ElementAt", "ElementAtOrDefault", "Unwrap", "Unwrap",
  667. }) {
  668. int count;
  669. if (!expected.TryGetValue(name, out count)) {
  670. count = 0;
  671. }
  672. expected[name] = count + 1;
  673. }
  674. var methods = ReflectionUtils.GetVisibleExtensionMethods(typeof(Enumerable).Assembly);
  675. new List<MethodInfo>(ReflectionUtils.GetVisibleExtensionMethodsSlow(typeof(Enumerable).Assembly));
  676. Dictionary<string, int> actual = new Dictionary<string, int>();
  677. foreach (MethodInfo method in methods) {
  678. int count;
  679. if (!actual.TryGetValue(method.Name, out count)) {
  680. count = 0;
  681. }
  682. actual[method.Name] = count + 1;
  683. }
  684. foreach (string name in actual.Keys) {
  685. Assert(expected.ContainsKey(name));
  686. Assert(expectExact ? expected[name] == actual[name] : expected[name] >= actual[name]);
  687. }
  688. }
  689. public void ClrExtensionMethods1() {
  690. Context.ObjectClass.SetConstant("SystemCoreAssembly", typeof(Expression).Assembly.FullName);
  691. TestOutput(@"
  692. load_assembly SystemCoreAssembly
  693. using_clr_extensions System::Linq
  694. a = System::Array[Fixnum].new([1,2,3])
  695. p a.first_or_default
  696. #TODO: p a.method(:of_type).of(Fixnum).call.to_a #=> [1, 2, 3]
  697. ", @"
  698. 1
  699. ");
  700. }
  701. /// <summary>
  702. /// Loads an assembly that defines more extension methods in the given namespace.
  703. /// </summary>
  704. public void ClrExtensionMethods2() {
  705. Context.ObjectClass.SetConstant("SystemCoreAssembly", typeof(Expression).Assembly.FullName);
  706. Context.ObjectClass.SetConstant("DummyLinqAssembly", typeof(System.Linq.Dummy).Assembly.FullName);
  707. TestOutput(@"
  708. load_assembly DummyLinqAssembly
  709. using_clr_extensions System::Linq
  710. load_assembly SystemCoreAssembly
  711. p System::Array[Fixnum].new([1,2,3]).first_or_default
  712. ", @"
  713. 1
  714. ");
  715. }
  716. /// <summary>
  717. /// Extension methods not available by default onlty after their declaring namespace is "used".
  718. /// </summary>
  719. public void ClrExtensionMethods3() {
  720. Context.ObjectClass.SetConstant("SystemCoreAssembly", typeof(Expression).Assembly.FullName);
  721. Context.ObjectClass.SetConstant("DummyLinqAssembly", typeof(System.Linq.Dummy).Assembly.FullName);
  722. TestOutput(@"
  723. load_assembly DummyLinqAssembly
  724. load_assembly SystemCoreAssembly
  725. a = System::Array[Fixnum].new([1,2,3])
  726. a.first_or_default rescue p $!
  727. using_clr_extensions System::Linq
  728. p a.first_or_default
  729. ", @"
  730. #<NoMethodError: undefined method `first_or_default' for [1, 2, 3]:System::Int32[]>
  731. 1
  732. ");
  733. }
  734. /// <summary>
  735. /// Extension methods defined using generic parameters and constraints.
  736. /// </summary>
  737. public void ClrExtensionMethods4() {
  738. Runtime.LoadAssembly(typeof(IronRubyTests.ExtensionMethods2.EMs).Assembly);
  739. TestOutput(@"
  740. L = System::Collections::Generic::List
  741. D = System::Collections::Generic::Dictionary
  742. using_clr_extensions IronRubyTests::ExtensionMethods2
  743. include IronRubyTests::ExtensionMethods2
  744. puts L[X].new.f1
  745. L[A].new.f1 rescue puts '!f1'
  746. puts D[B, A].new.f2
  747. puts D[A, A].new.f2
  748. D[A, X].new.f2 rescue puts '!f2'
  749. puts f3 = L[X].new.method(:f3)
  750. puts f3.of(X, Object)[1]
  751. puts L[Y].new.f3(X.new)
  752. L[A].new.f3(X.new) rescue puts '!f3'
  753. puts S.new.f4
  754. puts 1.f4
  755. #TODO: A.new.method(:f4) rescue p $!
  756. A.new.f4 rescue puts '!f4'
  757. puts A.new.f5
  758. puts B.new.f5
  759. class A; def f5; 'Ruby f5'; end; end
  760. puts A.new.f5
  761. puts B.new.f5 # f5 is an extension on all types (TODO)
  762. puts System::Array[A].new(1).f6
  763. System::Array[Fixnum].new(1).f6 rescue puts '!f6'
  764. puts L[System::Array[D[B, L[A]]]].new.f6
  765. L[System::Array[D[B, L[Fixnum]]]].new.f6 rescue puts '!f6'
  766. ", @"
  767. f1
  768. !f1
  769. f2
  770. f2
  771. !f2
  772. #<Method: System::Collections::Generic::List[IronRubyTests::ExtensionMethods2::X]#f3>
  773. f3
  774. f3
  775. !f3
  776. f4
  777. f4
  778. !f4
  779. f5
  780. f5
  781. Ruby f5
  782. Ruby f5
  783. f6
  784. !f6
  785. f6
  786. !f6
  787. ");
  788. }
  789. /// <summary>
  790. /// Extension methods are available on CLR interfaces implemented by Ruby classes.
  791. /// </summary>
  792. public void ClrExtensionMethods5() {
  793. #if TODO
  794. Runtime.LoadAssembly(typeof(System.Linq.Enumerable).Assembly);
  795. XTestOutput(@"
  796. using_clr_extensions System::Linq
  797. class Sequence
  798. include System::Collections::Generic::IEnumerable[Object]
  799. def initialize array
  800. @array = array
  801. end
  802. def get_enumerator
  803. @array.GetEnumerator()
  804. end
  805. end
  806. class Array
  807. def to_seq
  808. Sequence.new self
  809. end
  810. end
  811. a = Sequence.new [1, 2, 3]
  812. p a.select(lambda { |n| n * 2 })
  813. ", @"
  814. [2, 3, 6]
  815. ");
  816. #endif
  817. }
  818. #endregion
  819. #region Overloads: Inheritance, Selection
  820. public static class OverloadInheritance1 {
  821. public class A {
  822. public string Foo(int a, int b, int c) {
  823. return "Foo: " + a.ToString() + ", " + b.ToString() + ", " + c.ToString();
  824. }
  825. public string Skip() {
  826. return "Skip";
  827. }
  828. }
  829. public class B : A {
  830. public string Foo(int a) {
  831. return "Foo: " + a.ToString();
  832. }
  833. public virtual string Foo(int a, int b) {
  834. return "Foo: " + a.ToString() + ", " + b.ToString();
  835. }
  836. public string Bar(int a) {
  837. return "Bar: " + a.ToString();
  838. }
  839. public string Hidden(int a) {
  840. return "Hidden: " + a.ToString();
  841. }
  842. public string Middle(int a) {
  843. return "Middle: " + a.ToString();
  844. }
  845. }
  846. public class C : B {
  847. public new string Foo(int a) {
  848. return "NewFoo: " + a.ToString();
  849. }
  850. public override string Foo(int a, int b) {
  851. return "OverriddenFoo: " + a.ToString() + ", " + b.ToString();
  852. }
  853. public string Bar(int a, int b) {
  854. return "Bar: " + a.ToString() + ", " + b.ToString();
  855. }
  856. public string Hidden(int a, int b) {
  857. return "Hidden: " + a.ToString() + ", " + b.ToString();
  858. }
  859. public string Skip(int a) {
  860. return "Skip: " + a.ToString();
  861. }
  862. }
  863. }
  864. public void ClrOverloadInheritance1() {
  865. Context.ObjectClass.SetConstant("Obj", new OverloadInheritance1.C());
  866. AssertOutput(() => CompilerTest(@"
  867. puts Obj.foo(1)
  868. puts Obj.foo(1, 2)
  869. puts Obj.foo(1, 2, 3)
  870. puts Obj.bar(1)
  871. puts Obj.bar(1, 2)
  872. puts Obj.middle(1)
  873. puts Obj.skip
  874. puts Obj.skip(1)
  875. Obj.GetHashCode
  876. "), @"
  877. NewFoo: 1
  878. OverriddenFoo: 1, 2
  879. Foo: 1, 2, 3
  880. Bar: 1
  881. Bar: 1, 2
  882. Middle: 1
  883. Skip
  884. Skip: 1
  885. ");
  886. AssertOutput(() => CompilerTest(@"
  887. p Obj.method(:foo)
  888. p Obj.method(:bar)
  889. p Obj.method(:middle)
  890. p Obj.method(:skip)
  891. "), @"
  892. #<Method: *C#foo>
  893. #<Method: *C#bar>
  894. #<Method: *C(*B)#middle>
  895. #<Method: *C#skip>
  896. ", OutputFlags.Match);
  897. // hides Hidden method when called using mangled name "hidden":
  898. Context.GetClass(typeof(OverloadInheritance1.B)).HideMethod("hidden");
  899. AssertOutput(() => CompilerTest(@"
  900. puts Obj.hidden(1) rescue puts 'error'
  901. puts Obj.Hidden(1)
  902. puts Obj.hidden(1, 2)
  903. puts Obj.Hidden(1, 2)
  904. "), @"
  905. error
  906. Hidden: 1
  907. Hidden: 1, 2
  908. Hidden: 1, 2
  909. ");
  910. }
  911. public static class OverloadInheritance2 {
  912. public class A { public virtual string f(int a) { return "f1"; } }
  913. public class B : A { }
  914. public class C : B { }
  915. public class D : C { public virtual string f(int a, int b) { return "f2"; } }
  916. public class E : D { }
  917. public class F : E { public virtual string f(int a, int b, int c, int d) { return "f4"; } }
  918. public class G : F { }
  919. public class X : B { public virtual string f(int a, int b, int c) { return "f3"; } }
  920. public class Y : X { }
  921. public static void Load(RubyContext/*!*/ context) {
  922. context.ObjectClass.SetConstant("A", context.GetClass(typeof(A)));
  923. context.ObjectClass.SetConstant("B", context.GetClass(typeof(B)));
  924. context.ObjectClass.SetConstant("C", context.GetClass(typeof(C)));
  925. context.ObjectClass.SetConstant("D", context.GetClass(typeof(D)));
  926. context.ObjectClass.SetConstant("E", context.GetClass(typeof(E)));
  927. context.ObjectClass.SetConstant("F", context.GetClass(typeof(F)));
  928. context.ObjectClass.SetConstant("G", context.GetClass(typeof(G)));
  929. context.ObjectClass.SetConstant("X", context.GetClass(typeof(X)));
  930. context.ObjectClass.SetConstant("Y", context.GetClass(typeof(Y)));
  931. }
  932. }
  933. /// <summary>
  934. /// Dynamic site and group caching.
  935. /// </summary>
  936. public void ClrOverloadInheritance2() {
  937. OverloadInheritance2.Load(Context);
  938. // method definition hides overloads:
  939. AssertOutput(() => CompilerTest(@"
  940. puts E.new.f(1,2) # marks D::f2 and A::f1 as used in d.s.
  941. class C; def f; 'f:C'; end; end # overrides A::f1 => invalidates all 'f'-groups in subtree of C
  942. puts E.new.f(1) rescue puts 'error' # recreates D::f2 => A::f1 not visible
  943. puts E.new.f(1,2) # D::f still visible => marked as used in d.s.
  944. "), @"
  945. f2
  946. error
  947. f2
  948. ");
  949. // module inclusion hides overloads:
  950. AssertOutput(() => CompilerTest(@"
  951. puts Y.new.f(1)
  952. module M; def f; 'f:M' end; end
  953. class X; include M; end # hides A::f1, but not X::f3
  954. puts Y.new.f(1) rescue puts 'error'
  955. puts Y.new.f(1,2,3)
  956. "), @"
  957. f1
  958. error
  959. f3
  960. ");
  961. }
  962. public void ClrOverloadInheritance3() {
  963. OverloadInheritance2.Load(Context);
  964. // method definition hides overloads:
  965. AssertOutput(() => CompilerTest(@"
  966. p D.instance_method(:f).clr_members.collect { |x| x.to_string } # creates groups in A and D that are not used in d.s.
  967. class B; def f; 'f:B'; end; end # hides A::f1
  968. p D.instance_method(:f).clr_members.collect { |x| x.to_string } # only one overload should be present in the group
  969. "), @"
  970. ['System.String f(Int32)', 'System.String f(Int32, Int32)']
  971. ['System.String f(Int32, Int32)']
  972. ");
  973. }
  974. public void ClrOverloadInheritance4() {
  975. OverloadInheritance2.Load(Context);
  976. AssertOutput(() => CompilerTest(@"
  977. puts D.new.f(1)
  978. puts D.new.f(1,2)
  979. class B;
  980. def f; 'f:B'; end
  981. end
  982. puts D.new.f(1) rescue puts 'error'
  983. puts D.new.f(1,2)
  984. class B
  985. remove_method :f # f not used in DS, DS needs to be invalidated though
  986. end
  987. puts D.new.f(1)
  988. puts D.new.f(1,2)
  989. "), @"
  990. f1
  991. f2
  992. error
  993. f2
  994. f1
  995. f2
  996. ");
  997. }
  998. /// <summary>
  999. /// Removing an overload barrier.
  1000. /// </summary>
  1001. public void ClrOverloadInheritance5() {
  1002. OverloadInheritance2.Load(Context);
  1003. AssertOutput(() => CompilerTest(@"
  1004. puts E.new.f(1)
  1005. class C; def f; 'f:C'; end; end
  1006. E.new.f(1) rescue puts 'error'
  1007. puts E.new.f(1,2)
  1008. puts G.new.f(1,2,3,4) # group created after C:f barrier defined
  1009. C.send :remove_method, :f
  1010. puts G.new.f(1)
  1011. puts E.new.f(1)
  1012. "), @"
  1013. f1
  1014. error
  1015. f2
  1016. f4
  1017. f1
  1018. f1
  1019. ");
  1020. }
  1021. /// <summary>
  1022. /// Removing an overload barrier.
  1023. /// </summary>
  1024. public void ClrOverloadInheritance6() {
  1025. OverloadInheritance2.Load(Context);
  1026. TestOutput(@"
  1027. class E; def f; 'f:E'; end; end;
  1028. f = F.new
  1029. puts f.f(1,2,3,4) # creates { f4 } group on F
  1030. class E; remove_method(:f); end # invalidates group on F
  1031. puts f.f(1)
  1032. ", @"
  1033. f4
  1034. f1
  1035. ");
  1036. }
  1037. /// <summary>
  1038. /// Removing an overload barrier.
  1039. /// </summary>
  1040. public void ClrOverloadInheritance7() {
  1041. OverloadInheritance2.Load(Context);
  1042. TestOutput(@"
  1043. D.new.f(1,2) # creates A: {f1} and D: {f1, f2} groups
  1044. class E; def f; 'f:E'; end; end;
  1045. puts F.new.f(1,2,3,4) # creates { f4 } group on F, sets E#f.InvalidateOnRemoval
  1046. class C; def f; 'f:C'; end; end; # invalidates D group, doesn't invalidate F group as it doesn't contain any overloads from above
  1047. class E; remove_method :f; end; # invalidates group on F
  1048. puts F.new.f(1,2)
  1049. puts F.new.f(1,2,3,4)
  1050. F.new.f(1) rescue puts '!f1'
  1051. ", @"
  1052. f4
  1053. f2
  1054. f4
  1055. !f1
  1056. ");
  1057. }
  1058. public void ClrOverloadInheritance_ExtensionMethods1() {
  1059. Runtime.LoadAssembly(Assembly.GetExecutingAssembly());
  1060. OverloadInheritance2.Load(Context);
  1061. TestOutput(@"
  1062. using_clr_extensions IronRubyTests::ExtensionMethods1
  1063. d = D.new
  1064. puts d.f(1) # f1 on A
  1065. puts d.f(1,2,3,4,5) # e5 on C
  1066. puts d.f(1,2,3,4,5,6) # e6 on A
  1067. class B; def f; end; end
  1068. d.f(1) rescue p $! # f1 on A
  1069. puts d.f(1,2,3,4,5) # e5 on C
  1070. d.f(1,2,3,4,5,6) rescue p $! # e6 on A
  1071. class B; remove_method :f; end
  1072. puts d.f(1) # f1 on A
  1073. puts d.f(1,2,3,4,5) # e5 on C
  1074. puts d.f(1,2,3,4,5,6) # e6 on A
  1075. ", @"
  1076. f1
  1077. e5
  1078. e6
  1079. #<ArgumentError: wrong number of arguments (1 for 2)>
  1080. e5
  1081. #<ArgumentError: wrong number of arguments (6 for 5)>
  1082. f1
  1083. e5
  1084. e6
  1085. "
  1086. );
  1087. }
  1088. public void ClrOverloadInheritance_ExtensionMethods2() {
  1089. Runtime.LoadAssembly(Assembly.GetExecutingAssembly());
  1090. OverloadInheritance2.Load(Context);
  1091. TestOutput(@"
  1092. using_clr_extensions nil
  1093. puts F.new.f(1,2,3,4,5,6,7) # no namespace
  1094. using_clr_extensions IronRubyTests::ExtensionMethods1
  1095. puts F.new.f(1,2,3,4) # same signatures => regular method is preferred
  1096. ", @"
  1097. e7
  1098. f4
  1099. "
  1100. );
  1101. }
  1102. public class OverloadInheritance_ClrMembers1 {
  1103. public class A {
  1104. public int foo(int a) { return 1; }
  1105. public int Foo(int a) { return 2; }
  1106. }
  1107. public class B : A {
  1108. public int Foo(short a) { return 3; }
  1109. }
  1110. public class C : B {
  1111. public int foo(bool a) { return 4; }
  1112. }
  1113. public class D : C {
  1114. public int Foo(double a) { return 5; }
  1115. }
  1116. public static void Load(RubyContext/*!*/ context) {
  1117. context.ObjectClass.SetConstant("A", context.GetClass(typeof(A)));
  1118. context.ObjectClass.SetConstant("B", context.GetClass(typeof(B)));
  1119. context.ObjectClass.SetConstant("C", context.GetClass(typeof(C)));
  1120. context.ObjectClass.SetConstant("D", context.GetClass(typeof(D)));
  1121. }
  1122. }
  1123. /// <summary>
  1124. /// Method group should include methods of both casings.
  1125. /// It might depend on the order of method calls what overloads are available otherwise.
  1126. /// D.new.foo finds Foo and
  1127. /// - includes [foo(double), foo(int)] into the group if C.new.foo was invoked previously
  1128. /// - includes [Foo(bool)] into the group otherwise.
  1129. /// </summary>
  1130. public void ClrOverloadInheritance_ClrMembers1() {
  1131. OverloadInheritance_ClrMembers1.Load(Context);
  1132. TestOutput(@"
  1133. p C.new.method(:foo).clr_members.size
  1134. p D.new.method(:foo).clr_members.size
  1135. p A.new.method(:foo).clr_members.size
  1136. p B.new.method(:foo).clr_members.size
  1137. ", @"
  1138. 4
  1139. 5
  1140. 2
  1141. 3
  1142. ");
  1143. TestOutput(@"
  1144. p C.new.method(:Foo).clr_members.size
  1145. p D.new.method(:Foo).clr_members.size
  1146. p A.new.method(:Foo).clr_members.size
  1147. p B.new.method(:Foo).clr_members.size
  1148. ", @"
  1149. 2
  1150. 3
  1151. 1
  1152. 2
  1153. ");
  1154. // prefer overload whose name matches the call site exactly:
  1155. TestOutput(@"
  1156. p A.new.foo(1)
  1157. ", @"
  1158. 1
  1159. ");
  1160. }
  1161. // TODO: CLR overloads
  1162. // - alias/pri/pub/pro/mf/dm/generics/explicit-overload
  1163. public class OverloadedMethods {
  1164. public static string M1(RubyScope scope) {
  1165. return "M1()";
  1166. }
  1167. public static string M1(RubyContext context, MutableString foo) {
  1168. return "M1(String)";
  1169. }
  1170. public static string M1(BinaryOpStorage storage, RubyContext context, double foo) {
  1171. return "M1(Float)";
  1172. }
  1173. public static string M1(int foo, MutableString bar) {
  1174. return "M1(Fixnum, String)";
  1175. }
  1176. public static string M1(MutableString foo, MutableString bar) {
  1177. return "M1(String, String)";
  1178. }
  1179. public static string M1(int foo, params object[] bar) {
  1180. return "M1(Fixnum, Object*)";
  1181. }
  1182. public static string M1(int foo, object bar) {
  1183. return "M1(Fixnum, Object)";
  1184. }
  1185. public static string M1(int foo) {
  1186. return "M1(Fixnum)";
  1187. }
  1188. public static string M2(int foo) {
  1189. return "M2(Fixnum)";
  1190. }
  1191. public static string M2(object foo) {
  1192. return "M2(Object)";
  1193. }
  1194. public static string M2<T>(int foo) {
  1195. return "M2<" + typeof(T).Name + ">(Fixnum)";
  1196. }
  1197. public static string M2<T>(object foo) {
  1198. return "M2<" + typeof(T).Name + ">(Object)";
  1199. }
  1200. }
  1201. public void ClrOverloadSelection1() {
  1202. Context.ObjectClass.SetConstant("OM", Context.GetClass(typeof(OverloadedMethods)));
  1203. AssertOutput(() => CompilerTest(@"
  1204. m = OM.method(:M1)
  1205. puts m.overload.call
  1206. puts m.overload(String).call('')
  1207. puts m.overload(Float).call(1.0)
  1208. puts m.overload(Fixnum, String).call(1, '')
  1209. puts m.overload(String, String).call('', '')
  1210. puts m.overload(Fixnum, System::Array.of(Object)).call(1, 2, 3)
  1211. puts m.overload(Fixnum, Object).call(1, 2)
  1212. puts m.overload(Fixnum).call(1)
  1213. "), @"
  1214. M1()
  1215. M1(String)
  1216. M1(Float)
  1217. M1(Fixnum, String)
  1218. M1(String, String)
  1219. M1(Fixnum, Object*)
  1220. M1(Fixnum, Object)
  1221. M1(Fixnum)
  1222. "
  1223. );
  1224. AssertOutput(() => CompilerTest(@"
  1225. m = OM.method(:M2)
  1226. puts m.clr_members.size
  1227. puts m.of.clr_members.size
  1228. puts m.of(Object).clr_members.size
  1229. puts m.overload(Object).clr_members.size
  1230. puts m.of(Object).overload(Object).clr_members.size
  1231. puts m.overload(Object).of(Object).clr_members.size
  1232. "), @"
  1233. 4
  1234. 2
  1235. 2
  1236. 2
  1237. 1
  1238. 1
  1239. "
  1240. );
  1241. AssertOutput(() => CompilerTest(@"
  1242. m = OM.method(:M2)
  1243. puts m.call(1)
  1244. puts m.of(Float).call('')
  1245. puts m.of(Float).overload(Fixnum).call(1)
  1246. puts m.overload(Object).of(String).call(1)
  1247. "), @"
  1248. M2(Fixnum)
  1249. M2<Double>(Object)
  1250. M2<Double>(Fixnum)
  1251. M2<MutableString>(Object)
  1252. "
  1253. );
  1254. AssertOutput(() => CompilerTest(@"
  1255. m = OM.method(:M2)
  1256. m.overload(Object, String) rescue p $!
  1257. m.overload() rescue p $!
  1258. "), @"
  1259. #<ArgumentError: no overload of `M2' matches given parameter types>
  1260. #<ArgumentError: no overload of `M2' matches given parameter types>
  1261. "
  1262. );
  1263. // overlods called on a Ruby method
  1264. AssertOutput(() => CompilerTest(@"
  1265. def foo a,b
  1266. [a,b]
  1267. end
  1268. def bar a,*b
  1269. [a,*b]
  1270. end
  1271. p method(:foo).overload(Object, Object).call(1,2)
  1272. method(:foo).overload(Object) rescue p $!
  1273. p method(:bar).overload(Object).call(1)
  1274. p method(:bar).overload(Object, Object).call(1,2)
  1275. p method(:bar).overload(Object, Object, Object).call(1,2,3)
  1276. "), @"
  1277. [1, 2]
  1278. #<ArgumentError: no overload of `foo' matches given parameter types>
  1279. [1]
  1280. [1, 2]
  1281. [1, 2, 3]
  1282. "
  1283. );
  1284. // overlods called on a Ruby attribute accessor
  1285. AssertOutput(() => CompilerTest(@"
  1286. class C
  1287. attr_reader :foo
  1288. attr_writer :foo
  1289. c = new
  1290. c.foo = 1
  1291. p instance_method(:foo).overload.bind(c).call
  1292. instance_method(:foo=).overload(Object).bind(c).call(2)
  1293. p c.foo
  1294. end
  1295. "), @"
  1296. 1
  1297. 2
  1298. "
  1299. );
  1300. }
  1301. public static class OverloadSelection2 {
  1302. public class A {
  1303. public A() {
  1304. }
  1305. public A(int a) {
  1306. }
  1307. public A(RubyClass cls, double a) {
  1308. }
  1309. public static int Foo() { return 1; }
  1310. public static int Foo(RubyScope scope, BlockParam block, int a) { return 2; }
  1311. }
  1312. public class B : A {
  1313. public static int Foo(double a) { return 3; }
  1314. public static int Foo(RubyClass cls, string b) { return 4; }
  1315. }
  1316. public static void Load(RubyContext/*!*/ context) {
  1317. context.ObjectClass.SetConstant("A", context.GetClass(typeof(A)));
  1318. context.ObjectClass.SetConstant("B", context.GetClass(typeof(B)));
  1319. }
  1320. }
  1321. public void ClrOverloadSelection2() {
  1322. OverloadSelection2.Load(Context);
  1323. // static methods:
  1324. TestOutput(@"
  1325. m = B.method(:foo)
  1326. puts m.overload(Fixnum).clr_members.size # RubyScope and BlockParam are hidden
  1327. puts m.overload(System::String) rescue p $! # RubyClass is not hidden here
  1328. ", @"
  1329. 1
  1330. #<ArgumentError: no overload of `foo' matches given parameter types>
  1331. ");
  1332. // library methods:
  1333. TestOutput(@"
  1334. m = method(:print)
  1335. puts m.arity
  1336. puts m.overload().arity
  1337. puts m.overload(Object).arity
  1338. puts m.overload(System::Array[Object]).arity
  1339. ", @"
  1340. -1
  1341. 0
  1342. 1
  1343. -1
  1344. ");
  1345. }
  1346. public class ClassWithSlot1 {
  1347. public int Foo() {
  1348. return 1;
  1349. }
  1350. public override string ToString() {
  1351. return "base";
  1352. }
  1353. }
  1354. public class ClassWithNewSlot1 : ClassWithSlot1 {
  1355. public new string ToString() {
  1356. return "subclass";
  1357. }
  1358. public new int Foo() {
  1359. return 2;
  1360. }
  1361. }
  1362. public void ClrNewSlot1() {
  1363. Context.ObjectClass.SetConstant("NewSlot", Context.GetClass(typeof(ClassWithNewSlot1)));
  1364. Context.ObjectClass.SetConstant("Base", Context.GetClass(typeof(ClassWithSlot1)));
  1365. TestOutput(@"
  1366. c = NewSlot.new
  1367. p c.to_string
  1368. p c.clr_member(Object, :to_string).call
  1369. p c.foo
  1370. p c.clr_member(Base, :foo).call
  1371. ", @"
  1372. 'subclass'
  1373. 'base'
  1374. 2
  1375. 1
  1376. ");
  1377. }
  1378. #endregion
  1379. #region Interfaces
  1380. public class ClassWithInterfaces1 : IEnumerable {
  1381. public IEnumerator GetEnumerator() {
  1382. yield return 1;
  1383. yield return 2;
  1384. yield return 3;
  1385. }
  1386. }
  1387. public interface InterfaceFoo1 {
  1388. int Foo();
  1389. }
  1390. public interface InterfaceFoo2 {
  1391. int Foo();
  1392. int this[int i] { get; }
  1393. event Action Evnt;
  1394. int EvntValue { get; }
  1395. }
  1396. public interface InterfaceBar1 {
  1397. int Bar();
  1398. int Bar(int i);
  1399. }
  1400. public interface InterfaceBaz1 {
  1401. int Baz();
  1402. }
  1403. internal class InterfaceClassBase1 {
  1404. // inherited:
  1405. public IEnumerator GetEnumerator() {
  1406. yield return 1;

Large files files are truncated, but you can click here to view the full file