edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;C695629 File: RubyTests.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;C695629 (server) 1/9/2009 5:09 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;GenericMethodsAndOverloads @@ -315,6 +315,8 @@ ClrGenerics1, ClrMethods1, ClrMethodsVisibility1, + ClrGenericMethods1, + ClrOverloadSelection1, ClrInterfaces1, ClrRequireAssembly1, ClrInclude1, =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/ClrTests.cs;C656578 File: ClrTests.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/ClrTests.cs;C656578 (server) 1/9/2009 5:07 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/ClrTests.cs;GenericMethodsAndOverloads @@ -222,6 +222,239 @@ "); } +#pragma warning disable 67 // event not used + public class GenericMethods { + public static string M0() { + return "M0<" + typeof(T).Name + ">()"; + } + + public static string M1() { + return "M1()"; + } + + public static string M1() { + return "M1<" + typeof(T).Name + ">()"; + } + + public static string M1() { + return "M1<" + typeof(S).Name + ", " + typeof(T).Name + ">()"; + } + + public static string M1(int foo) { + return "M1<" + typeof(T).Name + ">(Fixnum)"; + } + + public static string M2(int foo) { + return "M2(Fixnum)"; + } + + public static string M2(int foo) { + return "M2<" + typeof(T).Name + ">(Fixnum)"; + } + + public static int Field; + public static object Property { get; set; } + public static event Action Event; + } +#pragma warning restore + + public void ClrGenericMethods1() { + Context.ObjectClass.SetConstant("GM", Context.GetClass(typeof(GenericMethods))); + AssertOutput(() => CompilerTest(@" +m = GM.method(:M1) +puts m.call +puts m.of().call +puts m.of(String).call +puts m.of(String, Fixnum).call +puts m.call(1) rescue p $! +puts m.of(String, String, String) rescue p $! +"), @" +M1() +M1() +M1() +M1() +# +# +" + ); + + AssertOutput(() => CompilerTest(@" +m = GM.method(:M2) +puts m.call(1) + +puts GM.method(:field).of(Fixnum) rescue p $! +puts GM.method(:property).of(Fixnum) rescue p $! +puts GM.method(:event).of(Fixnum) rescue p $! +"), @" +M2(Fixnum) +# +# +# +" + ); + } + + public class OverloadedMethods { + public static string M1(RubyScope scope) { + return "M1()"; + } + + public static string M1(RubyContext context, MutableString foo) { + return "M1(String)"; + } + + public static string M1(RubyContext context, BinaryOpStorage storage, double foo) { + return "M1(Float)"; + } + + public static string M1(int foo, MutableString bar) { + return "M1(Fixnum, String)"; + } + + public static string M1(MutableString foo, MutableString bar) { + return "M1(String, String)"; + } + + public static string M1(int foo, params object[] bar) { + return "M1(Fixnum, Object*)"; + } + + public static string M1(int foo, object bar) { + return "M1(Fixnum, Object)"; + } + + public static string M1(int foo) { + return "M1(Fixnum)"; + } + + + public static string M2(int foo) { + return "M2(Fixnum)"; + } + + public static string M2(object foo) { + return "M2(Object)"; + } + + public static string M2(int foo) { + return "M2<" + typeof(T).Name + ">(Fixnum)"; + } + + public static string M2(object foo) { + return "M2<" + typeof(T).Name + ">(Object)"; + } + } + + public void ClrOverloadSelection1() { + Context.ObjectClass.SetConstant("OM", Context.GetClass(typeof(OverloadedMethods))); + Runtime.LoadAssembly(typeof(object).Assembly); + + AssertOutput(() => CompilerTest(@" +m = OM.method(:M1) +puts m.overloads.call +puts m.overloads(String).call('') +puts m.overloads(Float).call(1.0) +puts m.overloads(Fixnum, String).call(1, '') +puts m.overloads(String, String).call('', '') +puts m.overloads(Fixnum, System::Array.of(Object)).call(1, 2, 3) +puts m.overloads(Fixnum, Object).call(1, 2) +puts m.overloads(Fixnum).call(1) +"), @" +M1() +M1(String) +M1(Float) +M1(Fixnum, String) +M1(String, String) +M1(Fixnum, Object*) +M1(Fixnum, Object) +M1(Fixnum) +" + ); + + AssertOutput(() => CompilerTest(@" +m = OM.method(:M2) +puts m.clr_members.size +puts m.of(Object).clr_members.size +puts m.overloads(Object).clr_members.size +puts m.of(Object).overloads(Object).clr_members.size +puts m.overloads(Object).of(Object).clr_members.size +"), @" +4 +2 +2 +1 +1 +" + ); + + AssertOutput(() => CompilerTest(@" +m = OM.method(:M2) +puts m.call(1) +puts m.of(Float).call('') +puts m.of(Float).overloads(Fixnum).call(1) +puts m.overloads(Object).of(String).call(1) +"), @" +M2(Fixnum) +M2(Object) +M2(Fixnum) +M2(Object) +" + ); + + AssertOutput(() => CompilerTest(@" +m = OM.method(:M2) +m.overloads(Object, String) rescue p $! +m.overloads() rescue p $! +"), @" +# +# +" + ); + + // overlods called on a Ruby method + AssertOutput(() => CompilerTest(@" +def foo a,b + [a,b] +end + +def bar a,*b + [a,*b] +end + +p method(:foo).overloads(Object, Object).call(1,2) +method(:foo).overloads(Object) rescue p $! + +p method(:bar).overloads(Object).call(1) +p method(:bar).overloads(Object, Object).call(1,2) +p method(:bar).overloads(Object, Object, Object).call(1,2,3) +"), @" +[1, 2] +# +[1] +[1, 2] +[1, 2, 3] +" + ); + + // overlods called on a Ruby attribute accessor + AssertOutput(() => CompilerTest(@" +class C + attr_reader :foo + attr_writer :foo + + c = new + c.foo = 1 + p instance_method(:foo).overloads.bind(c).call + instance_method(:foo=).overloads(Object).bind(c).call(2) + p c.foo +end +"), @" +1 +2 +" + ); + } + public class ClassWithInterfaces1 : IEnumerable { public IEnumerator GetEnumerator() { yield return 1; @@ -559,6 +792,5 @@ test "); } - } } =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializers.Generated.cs;C695629 File: Initializers.Generated.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializers.Generated.cs;C695629 (server) 1/9/2009 6:11 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializers.Generated.cs;GenericMethodsAndOverloads @@ -3186,6 +3186,18 @@ new System.Func(IronRuby.Builtins.MethodOps.Clone), }); + module.DefineLibraryMethod("clr_members", 0x51, new System.Delegate[] { + new System.Func(IronRuby.Builtins.MethodOps.GetClrMembers), + }); + + module.DefineLibraryMethod("of", 0x51, new System.Delegate[] { + new System.Func(IronRuby.Builtins.MethodOps.BindGenericParameters), + }); + + module.DefineLibraryMethod("overloads", 0x51, new System.Delegate[] { + new System.Func(IronRuby.Builtins.MethodOps.GetOverloads), + }); + module.DefineLibraryMethod("to_proc", 0x51, new System.Delegate[] { new System.Func(IronRuby.Builtins.MethodOps.ToProc), }); @@ -4176,9 +4188,9 @@ }); module.DefineLibraryMethod("gsub", 0x51, new System.Delegate[] { + new System.Func(IronRuby.Builtins.MutableStringOps.ReplaceAll), new System.Func, IronRuby.Runtime.RubyScope, IronRuby.Runtime.BlockParam, IronRuby.Builtins.MutableString, IronRuby.Builtins.RubyRegex, System.Object>(IronRuby.Builtins.MutableStringOps.BlockReplaceAll), new System.Func, IronRuby.Runtime.RubyScope, IronRuby.Runtime.BlockParam, IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.BlockReplaceAll), - new System.Func(IronRuby.Builtins.MutableStringOps.ReplaceAll), }); module.DefineLibraryMethod("gsub!", 0x51, new System.Delegate[] { @@ -5503,6 +5515,18 @@ new System.Func(IronRuby.Builtins.UnboundMethod.Clone), }); + module.DefineLibraryMethod("clr_members", 0x51, new System.Delegate[] { + new System.Func(IronRuby.Builtins.UnboundMethod.GetClrMembers), + }); + + module.DefineLibraryMethod("of", 0x51, new System.Delegate[] { + new System.Func(IronRuby.Builtins.UnboundMethod.BingGenericParameters), + }); + + module.DefineLibraryMethod("overloads", 0x51, new System.Delegate[] { + new System.Func(IronRuby.Builtins.UnboundMethod.GetOverloads), + }); + module.DefineLibraryMethod("to_s", 0x51, new System.Delegate[] { new System.Func(IronRuby.Builtins.UnboundMethod.ToS), }); =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/MethodOps.cs;C669880 File: MethodOps.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/MethodOps.cs;C669880 (server) 1/9/2009 5:18 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/MethodOps.cs;GenericMethodsAndOverloads @@ -71,6 +71,37 @@ return new UnboundMethod(self.GetTargetClass(), self.Name, self.Info); } + internal static RubyMemberInfo/*!*/ BindGenericParameters(RubyContext/*!*/ context, RubyMemberInfo/*!*/ info, string/*!*/ name, object[]/*!*/ typeArgs) { + RubyMemberInfo result = info.TryBindGenericParameters(Protocols.ToTypes(context, typeArgs)); + if (result == null) { + throw RubyExceptions.CreateArgumentError(String.Format("wrong number of generic arguments for `{0}'", name)); + } + return result; + } + + internal static RubyMemberInfo/*!*/ GetOverloads(RubyContext/*!*/ context, RubyMemberInfo/*!*/ info, string/*!*/ name, object[]/*!*/ typeArgs) { + RubyMemberInfo result = info.TrySelectOverload(Protocols.ToTypes(context, typeArgs)); + if (result == null) { + throw RubyExceptions.CreateArgumentError(String.Format("no overload of `{0}' matches given parameter types", name)); + } + return result; + } + + [RubyMethod("of")] + public static RubyMethod/*!*/ BindGenericParameters(RubyContext/*!*/ context, RubyMethod/*!*/ self, [NotNull]params object[]/*!*/ typeArgs) { + return new RubyMethod(self.Target, BindGenericParameters(context, self.Info, self.Name, typeArgs), self.Name); + } + + [RubyMethod("overloads")] + public static RubyMethod/*!*/ GetOverloads(RubyContext/*!*/ context, RubyMethod/*!*/ self, [NotNull]params object[]/*!*/ parameterTypes) { + return new RubyMethod(self.Target, GetOverloads(context, self.Info, self.Name, parameterTypes), self.Name); + } + + [RubyMethod("clr_members")] + public static RubyArray/*!*/ GetClrMembers(RubyMethod/*!*/ self) { + return new RubyArray(self.Info.GetMembers()); + } + #endregion } } =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/UnboundMethod.cs;C669880 File: UnboundMethod.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/UnboundMethod.cs;C669880 (server) 1/9/2009 6:07 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/UnboundMethod.cs;GenericMethodsAndOverloads @@ -23,7 +23,7 @@ namespace IronRuby.Builtins { [RubyClass("UnboundMethod")] - public class UnboundMethod : Object { + public class UnboundMethod { private readonly string/*!*/ _name; private readonly RubyMemberInfo/*!*/ _info; private readonly RubyModule/*!*/ _targetConstraint; @@ -111,6 +111,21 @@ return result; } + [RubyMethod("of")] + public static UnboundMethod/*!*/ BingGenericParameters(RubyContext/*!*/ context, UnboundMethod/*!*/ self, [NotNull]params object[]/*!*/ typeArgs) { + return new UnboundMethod(self.TargetConstraint, self.Name, MethodOps.BindGenericParameters(context, self.Info, self.Name, typeArgs)); + } + + [RubyMethod("overloads")] + public static UnboundMethod/*!*/ GetOverloads(RubyContext/*!*/ context, UnboundMethod/*!*/ self, [NotNull]params object[]/*!*/ parameterTypes) { + return new UnboundMethod(self.TargetConstraint, self.Name, MethodOps.GetOverloads(context, self.Info, self.Name, parameterTypes)); + } + + [RubyMethod("clr_members")] + public static RubyArray/*!*/ GetClrMembers(UnboundMethod/*!*/ self) { + return new RubyArray(self.Info.GetMembers()); + } + #endregion } } =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Utils.cs;C633889 File: Utils.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Utils.cs;C633889 (server) 1/9/2009 6:26 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Utils.cs;GenericMethodsAndOverloads @@ -17,9 +17,12 @@ using Microsoft.Scripting.Utils; using System.Diagnostics; using System.Text; +using System.Reflection; namespace IronRuby.Runtime { public static class Utils { + internal static readonly MemberInfo[] EmptyMemberInfos = new MemberInfo[0]; + public static class Array { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")] public static readonly byte[] EmptyBytes = new byte[0]; =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyAccessorInfo.cs;C651054 File: RubyAccessorInfo.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyAccessorInfo.cs;C651054 (server) 1/9/2009 6:25 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyAccessorInfo.cs;GenericMethodsAndOverloads @@ -13,19 +13,16 @@ * * ***************************************************************************/ -using Microsoft.Scripting; -using Microsoft.Scripting.Actions; -using System.Linq.Expressions; -using Microsoft.Scripting.Runtime; +using System; +using System.Diagnostics; +using System.Reflection; +using IronRuby.Builtins; +using IronRuby.Compiler; using Microsoft.Scripting.Utils; -using IronRuby.Builtins; using AstUtils = Microsoft.Scripting.Ast.Utils; namespace IronRuby.Runtime.Calls { - using Ast = System.Linq.Expressions.Expression; using AstFactory = IronRuby.Compiler.Ast.AstFactory; - using IronRuby.Compiler; - using System.Diagnostics; public abstract class RubyAttributeAccessorInfo : RubyMemberInfo { private readonly string/*!*/ _instanceVariableName; @@ -38,6 +35,10 @@ Debug.Assert(variableName.StartsWith("@")); _instanceVariableName = variableName; } + + public override MemberInfo/*!*/[]/*!*/ GetMembers() { + return Utils.EmptyMemberInfos; + } } public sealed class RubyAttributeReaderInfo : RubyAttributeAccessorInfo { @@ -56,6 +57,10 @@ protected internal override RubyMemberInfo/*!*/ Copy(RubyMemberFlags flags, RubyModule/*!*/ module) { return new RubyAttributeReaderInfo(flags, module, InstanceVariableName); } + + public override RubyMemberInfo TrySelectOverload(Type/*!*/[]/*!*/ parameterTypes) { + return parameterTypes.Length == 0 ? this : null; + } } public sealed class RubyAttributeWriterInfo : RubyAttributeAccessorInfo { @@ -78,5 +83,9 @@ protected internal override RubyMemberInfo/*!*/ Copy(RubyMemberFlags flags, RubyModule/*!*/ module) { return new RubyAttributeWriterInfo(flags, module, InstanceVariableName); } + + public override RubyMemberInfo TrySelectOverload(Type/*!*/[]/*!*/ parameterTypes) { + return parameterTypes.Length == 1 && parameterTypes[0] == typeof(object) ? this : null; + } } } =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyBinder.cs;C674241 File: RubyBinder.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyBinder.cs;C674241 (server) 1/12/2009 10:34 AM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyBinder.cs;GenericMethodsAndOverloads @@ -95,12 +95,8 @@ mandatory = 0; optional = 0; foreach (ParameterInfo parameterInfo in parameterInfos) { - if (parameterInfo.ParameterType == typeof(RubyScope)) { + if (IsHiddenParameter(parameterInfo)) { continue; - } else if (parameterInfo.ParameterType == typeof(RubyContext)) { - continue; - } else if (parameterInfo.ParameterType.IsSubclassOf(typeof(CallSite))) { - continue; } else if (parameterInfo.ParameterType == typeof(BlockParam)) { acceptsBlock = true; } else if (CompilerHelpers.IsParamArray(parameterInfo)) { @@ -118,6 +114,12 @@ } } + internal static bool IsHiddenParameter(ParameterInfo/*!*/ parameterInfo) { + return parameterInfo.ParameterType == typeof(RubyScope) + || parameterInfo.ParameterType == typeof(RubyContext) + || parameterInfo.ParameterType.IsSubclassOf(typeof(SiteLocalStorage)); + } + internal sealed class RubyContextArgBuilder : ArgBuilder { public RubyContextArgBuilder(ParameterInfo/*!*/ info) : base(info) { =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyCustomMethodInfo.cs;C695629 File: RubyCustomMethodInfo.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyCustomMethodInfo.cs;C695629 (server) 1/9/2009 6:27 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyCustomMethodInfo.cs;GenericMethodsAndOverloads @@ -13,6 +13,8 @@ * * ***************************************************************************/ +using System; +using System.Reflection; using Microsoft.Scripting.Actions; using Microsoft.Scripting.Runtime; using Microsoft.Scripting.Utils; @@ -36,5 +38,13 @@ protected internal override RubyMemberInfo/*!*/ Copy(RubyMemberFlags flags, RubyModule/*!*/ module) { return new RubyCustomMethodInfo(_ruleGenerator, flags, module); } + + public override MemberInfo/*!*/[]/*!*/ GetMembers() { + return new MemberInfo[] { _ruleGenerator.Method }; + } + + public override RubyMemberInfo TrySelectOverload(Type/*!*/[]/*!*/ parameterTypes) { + return this; + } } } =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyEventInfo.cs;C651054 File: RubyEventInfo.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyEventInfo.cs;C651054 (server) 1/9/2009 6:28 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyEventInfo.cs;GenericMethodsAndOverloads @@ -13,19 +13,19 @@ * * ***************************************************************************/ +using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.Scripting.Actions; using System.Linq.Expressions; using Microsoft.Scripting.Runtime; using Microsoft.Scripting.Utils; - +using Microsoft.Scripting.Actions; +using IronRuby.Compiler; using IronRuby.Builtins; namespace IronRuby.Runtime.Calls { using Ast = System.Linq.Expressions.Expression; - using IronRuby.Compiler; - + internal class RubyEventInfo : RubyMemberInfo { private readonly EventInfo/*!*/ _eventInfo; @@ -39,6 +39,14 @@ return new RubyEventInfo(_eventInfo, flags, module); } + public override MemberInfo/*!*/[]/*!*/ GetMembers() { + return new MemberInfo[] { _eventInfo }; + } + + public override RubyMemberInfo TrySelectOverload(Type/*!*/[]/*!*/ parameterTypes) { + return parameterTypes.Length == 0 ? this : null; + } + internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { if (args.Signature.HasBlock) { metaBuilder.Result = Methods.HookupEvent.OpCall( =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyFieldInfo.cs;C651054 File: RubyFieldInfo.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyFieldInfo.cs;C651054 (server) 1/9/2009 6:28 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyFieldInfo.cs;GenericMethodsAndOverloads @@ -13,9 +13,10 @@ * * ***************************************************************************/ +using System; using System.Reflection; +using System.Linq.Expressions; using Microsoft.Scripting.Actions; -using System.Linq.Expressions; using Microsoft.Scripting.Runtime; using Microsoft.Scripting.Utils; using IronRuby.Builtins; @@ -39,6 +40,14 @@ return new RubyFieldInfo(_fieldInfo, flags, module, _isSetter); } + public override MemberInfo/*!*/[]/*!*/ GetMembers() { + return new MemberInfo[] { _fieldInfo }; + } + + public override RubyMemberInfo TrySelectOverload(Type/*!*/[]/*!*/ parameterTypes) { + return parameterTypes.Length == 0 ? this : null; + } + internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { Expression expr = null; Expression instance = _fieldInfo.IsStatic ? null : Ast.Convert(args.TargetExpression, _fieldInfo.DeclaringType); =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyLambdaMethodInfo.cs;C651054 File: RubyLambdaMethodInfo.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyLambdaMethodInfo.cs;C651054 (server) 1/9/2009 6:28 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyLambdaMethodInfo.cs;GenericMethodsAndOverloads @@ -13,6 +13,9 @@ * * ***************************************************************************/ +using System; +using System.Diagnostics; +using System.Reflection; using Microsoft.Scripting; using Microsoft.Scripting.Actions; using Microsoft.Scripting.Runtime; @@ -21,7 +24,6 @@ namespace IronRuby.Runtime.Calls { using Ast = System.Linq.Expressions.Expression; - using System.Diagnostics; public class RubyLambdaMethodInfo : RubyMemberInfo { private readonly Proc/*!*/ _lambda; @@ -42,10 +44,19 @@ _definitionName = definitionName; } + public override MemberInfo/*!*/[]/*!*/ GetMembers() { + return new MemberInfo[] { _lambda.Dispatcher.Method.Method }; + } + protected internal override RubyMemberInfo/*!*/ Copy(RubyMemberFlags flags, RubyModule/*!*/ module) { return new RubyLambdaMethodInfo(_lambda, _definitionName, flags, module); } + public override RubyMemberInfo TrySelectOverload(Type/*!*/[]/*!*/ parameterTypes) { + return parameterTypes.Length == _lambda.Dispatcher.ParameterCount + && Array.TrueForAll(parameterTypes, (type) => type == typeof(object)) ? this : null; + } + internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { Debug.Assert(!args.Signature.HasBlock); =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyMemberInfo.cs;C695629 File: RubyMemberInfo.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyMemberInfo.cs;C695629 (server) 1/9/2009 5:43 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyMemberInfo.cs;GenericMethodsAndOverloads @@ -13,11 +13,13 @@ * * ***************************************************************************/ +using System; +using System.Diagnostics; +using System.Reflection; using Microsoft.Scripting.Actions; using Microsoft.Scripting.Runtime; using Microsoft.Scripting.Utils; using IronRuby.Builtins; -using System.Diagnostics; namespace IronRuby.Runtime.Calls { @@ -102,6 +104,28 @@ throw Assert.Unreachable; } + /// + /// Gets all the CLR members represented by this member info. + /// + public virtual MemberInfo/*!*/[]/*!*/ GetMembers() { + throw Assert.Unreachable; + } + + /// + /// Returns a copy of this member info that groups only those members of this member info that are generic + /// and of generic arity equal to the length of the given array of type arguments. Returns null if there are no such generic members. + /// All the members in the resulting info are constructed generic methods bound to the given type arguments. + /// + public virtual RubyMemberInfo TryBindGenericParameters(Type/*!*/[]/*!*/ typeArguments) { + return null; + } + + public virtual RubyMemberInfo TrySelectOverload(Type/*!*/[]/*!*/ parameterTypes) { + throw Assert.Unreachable; + } + + #region Dynamic Operations + internal virtual void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { throw Assert.Unreachable; } @@ -119,5 +143,7 @@ BuildSuperCallNoFlow(metaBuilder, args, name, declaringModule); metaBuilder.BuildControlFlow(args); } + + #endregion } } =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyMethodGroupInfo.cs;C695629 File: RubyMethodGroupInfo.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyMethodGroupInfo.cs;C695629 (server) 1/9/2009 5:45 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyMethodGroupInfo.cs;GenericMethodsAndOverloads @@ -101,17 +101,82 @@ // copy ctor private RubyMethodGroupInfo(RubyMethodGroupInfo/*!*/ info, RubyMemberFlags flags, RubyModule/*!*/ module) + : this(info, flags, module, info._methodBases) { + } + + // copy ctor + private RubyMethodGroupInfo(RubyMethodGroupInfo/*!*/ info, RubyMemberFlags flags, RubyModule/*!*/ module, IList methodBases) : base(flags, module) { - _methodBases = info._methodBases; + _methodBases = methodBases; _overloads = info._overloads; _isRubyMethod = info._isRubyMethod; _isClrStatic = info._isClrStatic; } + public override MemberInfo/*!*/[]/*!*/ GetMembers() { + return ArrayUtils.MakeArray(MethodBases); + } + protected internal override RubyMemberInfo/*!*/ Copy(RubyMemberFlags flags, RubyModule/*!*/ module) { return new RubyMethodGroupInfo(this, flags, module); } + public override RubyMemberInfo TryBindGenericParameters(Type/*!*/[]/*!*/ typeArguments) { + var boundMethods = new List(); + foreach (var method in MethodBases) { + if (typeArguments.Length == 0) { + boundMethods.Add(method); + } else if (method.IsGenericMethodDefinition && typeArguments.Length == method.GetGenericArguments().Length) { + Debug.Assert(!(method is ConstructorInfo)); + boundMethods.Add(((MethodInfo)method).MakeGenericMethod(typeArguments)); + } + } + + if (boundMethods.Count == 0) { + return null; + } + + return new RubyMethodGroupInfo(this, Flags, DeclaringModule, boundMethods); + } + + /// + /// Filters out methods that don't exactly match parameter types except for hidden parameters (RubyContext, RubyScope, site local storage). + /// + public override RubyMemberInfo TrySelectOverload(Type/*!*/[]/*!*/ parameterTypes) { + var boundMethods = new List(); + foreach (var method in MethodBases) { + if (IsOverloadSignature(method, parameterTypes)) { + boundMethods.Add(method); + } + } + + if (boundMethods.Count == 0) { + return null; + } + + return new RubyMethodGroupInfo(this, Flags, DeclaringModule, boundMethods); + } + + private static bool IsOverloadSignature(MethodBase/*!*/ method, Type/*!*/[]/*!*/ parameterTypes) { + var infos = method.GetParameters(); + int firstInfo = 0; + while (firstInfo < infos.Length && RubyBinder.IsHiddenParameter(infos[firstInfo])) { + firstInfo++; + } + + if (infos.Length - firstInfo != parameterTypes.Length) { + return false; + } + + for (int i = 0; i < parameterTypes.Length; i++) { + if (infos[firstInfo + i].ParameterType != parameterTypes[i]) { + return false; + } + } + + return true; + } + public override int Arity { get { int minParameters = Int32.MaxValue; =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyMethodInfo.cs;C695629 File: RubyMethodInfo.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyMethodInfo.cs;C695629 (server) 1/9/2009 6:30 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyMethodInfo.cs;GenericMethodsAndOverloads @@ -27,6 +27,7 @@ using AstFactory = IronRuby.Compiler.Ast.AstFactory; using AstUtils = Microsoft.Scripting.Ast.Utils; using Ast = System.Linq.Expressions.Expression; +using System.Reflection; namespace IronRuby.Runtime.Calls { public sealed class RubyMethodInfo : RubyMemberInfo { @@ -72,6 +73,16 @@ ); } + public override RubyMemberInfo TrySelectOverload(Type/*!*/[]/*!*/ parameterTypes) { + return parameterTypes.Length >= MandatoryParamCount + && (HasUnsplatParameter || parameterTypes.Length <= MandatoryParamCount + OptionalParamCount) + && Array.TrueForAll(parameterTypes, (type) => type == typeof(object)) ? this : null; + } + + public override MemberInfo/*!*/[]/*!*/ GetMembers() { + return new MemberInfo[] { _method.Method }; + } + public override int Arity { get { if (_optionalParamCount > 0) { ===================================================================