edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializer.Generated.cs;C429806 File: Initializer.Generated.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializer.Generated.cs;C429806 (server) 5/7/2008 10:44 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializer.Generated.cs;Reflection @@ -1814,6 +1814,10 @@ new Microsoft.Scripting.Utils.Action(Ruby.Builtins.Kernel.TerminateExecution), }); + module.DefineMethod("extend", 0x9, new System.Delegate[] { + new Microsoft.Scripting.Utils.Function(Ruby.Builtins.Kernel.Extend), + }); + module.DefineMethod("fail", 0xa, new System.Delegate[] { new Microsoft.Scripting.Utils.Action(Ruby.Builtins.Kernel.RaiseException), new Microsoft.Scripting.Utils.Action(Ruby.Builtins.Kernel.RaiseException), @@ -1969,6 +1973,11 @@ new Microsoft.Scripting.Utils.Function(Ruby.Builtins.Kernel.SendMessage), }); + module.DefineMethod("singleton_methods", 0x9, new System.Delegate[] { + new Microsoft.Scripting.Utils.Function(Ruby.Builtins.Kernel.GetSingletonMethods), + new Microsoft.Scripting.Utils.Function(Ruby.Builtins.Kernel.GetSingletonMethods), + }); + module.DefineMethod("sleep", 0xa, new System.Delegate[] { new System.Action(Ruby.Builtins.Kernel.Sleep), new Microsoft.Scripting.Utils.Function(Ruby.Builtins.Kernel.Sleep), @@ -2425,6 +2434,15 @@ new Microsoft.Scripting.Utils.Function(Ruby.Builtins.ModuleOps.DefineMethod), }); + module.DefineMethod("extend_object", 0xa, new System.Delegate[] { + new Microsoft.Scripting.Utils.Function(Ruby.Builtins.ModuleOps.ExtendObject), + new Microsoft.Scripting.Utils.Function(Ruby.Builtins.ModuleOps.ExtendObject), + }); + + module.DefineMethod("extended", 0xa, new System.Delegate[] { + new Microsoft.Scripting.Utils.Action(Ruby.Builtins.ModuleOps.ObjectExtended), + }); + module.DefineMethod("include", 0xa, new System.Delegate[] { new Microsoft.Scripting.Utils.Function(Ruby.Builtins.ModuleOps.Include), }); @@ -2434,7 +2452,7 @@ }); module.DefineMethod("included", 0xa, new System.Delegate[] { - new Microsoft.Scripting.Utils.Function(Ruby.Builtins.ModuleOps.Included), + new Microsoft.Scripting.Utils.Action(Ruby.Builtins.ModuleOps.Included), }); module.DefineMethod("included_modules", 0x9, new System.Delegate[] { =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/Kernel.cs;C429806 File: Kernel.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/Kernel.cs;C429806 (server) 5/7/2008 9:50 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/Kernel.cs;Reflection @@ -513,8 +513,33 @@ #endregion //display - //extend + [RubyMethod("extend")] + public static object Extend(CodeContext/*!*/ context, object self, [NotNull]RubyModule/*!*/ module, + [NotNull]params RubyModule/*!*/[]/*!*/ modules) { + Assert.NotNull(self, modules); + RubyUtils.RequireNonClasses(modules); + + // Kernel#extend_object inserts the module at the beginning of the object's singleton ancestors list; + // ancestors after extend: [modules[0], modules[1], ..., modules[N-1], self-singleton, ...] + for (int i = modules.Length - 1; i >= 0; i--) { + _ModuleExtentObjectSite.Invoke(context, modules[i], self); + _ModuleExtendedSite.Invoke(context, modules[i], self); + } + + _ModuleExtentObjectSite.Invoke(context, module, self); + _ModuleExtendedSite.Invoke(context, module, self); + + return self; + } + + private static readonly DynamicSite _ModuleExtentObjectSite = + DynamicSite.Create(RubySites.InstanceCallAction("extend_object", ArgumentKind.Simple)); + + private static readonly DynamicSite _ModuleExtendedSite = + DynamicSite.Create(RubySites.InstanceCallAction("extended", ArgumentKind.Simple)); + + #region frozen?, freeze, tainted?, taint, untaint [RubyMethod("frozen?")] @@ -725,12 +750,12 @@ //public_methods [RubyMethod("respond_to?")] - public static bool RespondTo(CodeContext/*!*/ context, object/*!*/ self, SymbolId name) { + public static bool RespondTo(CodeContext/*!*/ context, object self, SymbolId name) { return RubyUtils.GetExecutionContext(context).ResolveMethod(self, name) != null; } [RubyMethod("respond_to?")] - public static bool RespondTo(CodeContext/*!*/ context, object/*!*/ self, object name) { + public static bool RespondTo(CodeContext/*!*/ context, object self, object name) { return RubyUtils.GetExecutionContext(context).ResolveMethod(self, Protocols.CastToSymbol(context, name)) != null; } @@ -765,8 +790,19 @@ } #endregion - //singleton_methods + [RubyMethod("singleton_methods")] + public static RubyArray/*!*/ GetSingletonMethods(CodeContext/*!*/ context, object self) { + return GetSingletonMethods(context, self, true); + } + [RubyMethod("singleton_methods")] + public static RubyArray/*!*/ GetSingletonMethods(CodeContext/*!*/ context, object self, bool inherited) { + RubyClass immediateClass = RubyUtils.GetExecutionContext(context).GetImmediateClassOf(self); + return ModuleOps.GetInstanceMethods(immediateClass, inherited, + RubyMethodAttributes.Public | RubyMethodAttributes.Protected | RubyMethodAttributes.Singleton + ); + } + /// /// Returns a string containing a human-readable representation of obj. /// If not overridden, uses the to_s method to generate the string. @@ -790,8 +826,6 @@ return Kernel.FlowTaint(context, self, RubyUtils.ObjectToMutableString(context, self)); } - //type - #endregion #region Public Instance & Singleton Methods =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ModuleOps.cs;C431660 File: ModuleOps.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ModuleOps.cs;C431660 (server) 5/7/2008 9:46 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ModuleOps.cs;Reflection @@ -26,6 +26,7 @@ using System.Runtime.InteropServices; using System.ComponentModel; using System.Diagnostics; +using Microsoft.Scripting.Ast; namespace Ruby.Builtins { @@ -110,53 +111,56 @@ #endregion - #region extend_object, extended // TODO + #region extend_object, extended, include, included - // extend_object - // extended + [RubyMethod("extend_object", RubyMethodAttributes.PrivateInstance)] + public static RubyModule/*!*/ ExtendObject(RubyModule/*!*/ self, [NotNull]RubyModule/*!*/ extendedModule) { + // include self into extendedModule's singleton class + extendedModule.SingletonClass.IncludeModules(self); + return self; + } + + [RubyMethod("extend_object", RubyMethodAttributes.PrivateInstance)] + public static object ExtendObject(RubyModule/*!*/ self, object extendedObject) { + // include self into extendedObject's singleton + self.ExecutionContext.CreateSingletonClass(extendedObject).IncludeModules(self); + return extendedObject; + } - #endregion - - #region include, included // TODO - - internal static void RequireNonClasses(params RubyModule/*!*/[]/*!*/ modules) { - foreach (RubyModule module in modules) { - if (module.IsClass) { - throw RubyExceptions.CreateTypeError("wrong argument type Class (expected Module)"); - } - } + [RubyMethod("extended", RubyMethodAttributes.PrivateInstance)] + public static void ObjectExtended(RubyModule/*!*/ self, object extendedObject) { + // extendedObject has been extended by self, i.e. self has been included into extendedObject's singleton class } [RubyMethod("include", RubyMethodAttributes.PrivateInstance)] - public static RubyModule/*!*/ Include(CodeContext/*!*/ context, RubyModule/*!*/ self, [NotNull]params RubyModule[]/*!*/ modules) { + public static RubyModule/*!*/ Include(CodeContext/*!*/ context, RubyModule/*!*/ self, [NotNull]params RubyModule/*!*/[]/*!*/ modules) { Assert.NotNull(self, modules); - RequireNonClasses(modules); + RubyUtils.RequireNonClasses(modules); - // "include" inserts the module in the begining of the MRO - // so sequential includes follow a "last one wins" policy - // - // However, if several modules are passed to one "include" call, the - // first one ends up first in the MRO. - // - // So, we need to add the modules in reverse order here. + // Kernel#append_features inserts the module at the beginning of ancestors list; + // ancestors after include: [modules[0], modules[1], ..., modules[N-1], self, ...] for (int i = modules.Length - 1; i >= 0; i--) { - RubySites.ModuleAppendFeatures(context, modules[i], self); - RubySites.ModuleIncluded(context, modules[i], self); + _ModuleAppendFeaturesSite.Invoke(context, modules[i], self); + _ModuleIncludedSite.Invoke(context, modules[i], self); } return self; } + private static readonly DynamicSite _ModuleAppendFeaturesSite = + DynamicSite.Create(RubySites.InstanceCallAction("append_features", ArgumentKind.Simple)); + + private static readonly DynamicSite _ModuleIncludedSite = + DynamicSite.Create(RubySites.InstanceCallAction("included", ArgumentKind.Simple)); + [RubyMethod("included", RubyMethodAttributes.PrivateInstance)] - public static RubyModule/*!*/ Included(RubyModule/*!*/ self, RubyModule/*!*/ includedModule) { - // nop - return self; + public static void Included(RubyModule/*!*/ self, RubyModule/*!*/ owner) { + // self has been included into owner } [RubyMethod("append_features", RubyMethodAttributes.PrivateInstance)] - public static RubyModule/*!*/ AppendFeatures(RubyModule/*!*/ self, RubyModule/*!*/ includedModule) { - ContractUtils.RequiresNotNull(includedModule, "includedModule"); - includedModule.IncludeModules(self); + public static RubyModule/*!*/ AppendFeatures(RubyModule/*!*/ self, [NotNull]RubyModule/*!*/ owner) { + owner.IncludeModules(self); return self; } @@ -209,7 +213,6 @@ } if ((attributes & RubyMethodAttributes.Singleton) != 0) { - Debug.Assert(!module.SingletonClass.IsDummySingletonClass); module.SingletonClass.SetMethod(methodName, method); } @@ -478,7 +481,9 @@ public static RubyArray/*!*/ Ancestors(RubyModule/*!*/ self) { RubyArray ancestors = new RubyArray(); self.ForEachAncestor(true, delegate(RubyModule/*!*/ module) { - ancestors.Add(module); + if (!module.IsSingletonClass) { + ancestors.Add(module); + } return false; }); return ancestors; @@ -498,7 +503,7 @@ [RubyMethod("include?")] public static bool IncludesModule(RubyModule/*!*/ self, [NotNull]RubyModule/*!*/ other) { - RequireNonClasses(other); + RubyUtils.RequireNonClasses(other); return other != self && self.HasAncestor(other); } @@ -651,7 +656,7 @@ [RubyMethod("instance_methods")] public static RubyArray/*!*/ GetInstanceMethods(RubyModule/*!*/ self, bool inherited) { - return GetInstanceMethods(self, inherited, RubyMethodVisibility.Public); + return GetInstanceMethods(self, inherited, RubyMethodAttributes.PublicInstance); } [RubyMethod("private_instance_methods")] @@ -661,7 +666,7 @@ [RubyMethod("private_instance_methods")] public static RubyArray/*!*/ GetPrivateInstanceMethods(RubyModule/*!*/ self, bool inherited) { - return GetInstanceMethods(self, inherited, RubyMethodVisibility.Private); + return GetInstanceMethods(self, inherited, RubyMethodAttributes.PrivateInstance); } [RubyMethod("protected_instance_methods")] @@ -671,7 +676,7 @@ [RubyMethod("protected_instance_methods")] public static RubyArray/*!*/ GetProtectedInstanceMethods(RubyModule/*!*/ self, bool inherited) { - return GetInstanceMethods(self, inherited, RubyMethodVisibility.Protected); + return GetInstanceMethods(self, inherited, RubyMethodAttributes.ProtectedInstance); } [RubyMethod("public_instance_methods")] @@ -681,34 +686,48 @@ [RubyMethod("public_instance_methods")] public static RubyArray/*!*/ GetPublicInstanceMethods(RubyModule/*!*/ self, bool inherited) { - return GetInstanceMethods(self, inherited, RubyMethodVisibility.Public); + return GetInstanceMethods(self, inherited, RubyMethodAttributes.PublicInstance); } /// - /// inherited == false => get methods of all modules in ancestors until a class is hit (include the class's methods as well). + /// inherited == false, attributes & Instance != 0: + /// - get methods in the "self" module + /// - also include methods on singleton ancestor classes until a non-singleton module is reached + /// inherited == false, attributes & Singleton != 0: + /// - get methods in the "self" module only + /// - do not visit mixins nor super classes + /// inherited == true + /// - walk all ancestors until a non-singleton is reached (include "self" module anyways) + /// + /// Methods are filtered by visibility specified in attributes (mutliple visibilities could be specified). + /// A name undefined in a module is not visible in that module and its ancestors. + /// Method names are not duplicated in the result. /// - private static RubyArray/*!*/ GetInstanceMethods(RubyModule/*!*/ self, bool inherited, RubyMethodVisibility visibility) { + internal static RubyArray/*!*/ GetInstanceMethods(RubyModule/*!*/ self, bool inherited, RubyMethodAttributes attributes) { Dictionary visited = new Dictionary(); RubyArray result = new RubyArray(); + bool instanceMethods = (attributes & RubyMethodAttributes.Instance) != 0; + bool stop = false; self.ForEachInstanceMethod(true, delegate(RubyModule/*!*/ module, SymbolId name, RubyMemberInfo method) { if (method == null) { // notification received before any method of the module - + if (stop) { return true; } - if (!inherited && !module.IsSingletonClass) { - // stop in the next module - stop = true; + if (instanceMethods) { + stop = !inherited && !module.IsSingletonClass; + } else if ((!inherited || !module.IsSingletonClass) && module != self) { + return true; } } else if (method.IsUndefined) { visited.Add(name, true); - } else if (method.Visibility == visibility && !visited.ContainsKey(name)) { + } else if (((RubyMethodAttributes)method.Visibility & attributes) != 0 && !visited.ContainsKey(name)) { result.Add(new MutableString(name)); visited.Add(name, true); } =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/SingletonOps.cs;C429806 File: SingletonOps.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/SingletonOps.cs;C429806 (server) 5/7/2008 10:45 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/SingletonOps.cs;Reflection @@ -64,9 +64,9 @@ } [RubyMethod("include", RubyMethodAttributes.PublicInstance)] - public static RubyClass/*!*/ Include(CodeContext/*!*/ context, object/*!*/ self, params RubyModule[]/*!*/ modules) { + public static RubyClass/*!*/ Include(CodeContext/*!*/ context, object/*!*/ self, params RubyModule/*!*/[]/*!*/ modules) { ContractUtils.RequiresNotNullItems(modules, "modules"); - ModuleOps.RequireNonClasses(modules); + RubyUtils.RequireNonClasses(modules); RubyClass result = RubyUtils.GetExecutionContext(context).GetClassOf(self); result.IncludeModules(modules); =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyClass.cs;C429903 edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyModule.cs;C431660 File: RubyModule.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyModule.cs;C431660 (server) 5/8/2008 12:44 AM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyModule.cs;Reflection @@ -137,6 +137,11 @@ get { return ReferenceEquals(this, _executionContext.ObjectClass); } } + // for derived Ruby classes + protected RubyModule(CodeContext/*!*/ context) + : this(RubyUtils.GetExecutionContext(context), SymbolId.Empty, null, null, null) { + } + internal RubyModule(RubyExecutionContext/*!*/ context, SymbolId name, Action initializer, IAttributesCollection clrConstants, TypeTracker tracker) { Assert.NotNull(context); =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubySites.cs;C429806 File: RubySites.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubySites.cs;C429806 (server) 5/7/2008 10:00 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubySites.cs;Reflection @@ -143,20 +143,6 @@ return ModuleConstMissingSharedSite.Invoke(context, self, name); } - private static readonly DynamicSite ModuleAppendFeaturesSharedSite = DynamicSite.Create( - InstanceCallAction("append_features", ArgumentKind.Simple)); - - public static object ModuleAppendFeatures(CodeContext/*!*/ context, RubyModule self, RubyModule module) { - return ModuleAppendFeaturesSharedSite.Invoke(context, self, module); - } - - private static readonly DynamicSite ModuleIncludedSharedSite = DynamicSite.Create( - InstanceCallAction("included", ArgumentKind.Simple)); - - public static object ModuleIncluded(CodeContext/*!*/ context, RubyModule self, RubyModule module) { - return ModuleIncludedSharedSite.Invoke(context, self, module); - } - private static readonly DynamicSite ExceptionWithMessageSharedSite = DynamicSite.Create( InstanceCallAction("exception", ArgumentKind.Simple)); =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Generation/RubyTypeBuilder.cs;C428403 File: RubyTypeBuilder.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Generation/RubyTypeBuilder.cs;C428403 (server) 5/8/2008 12:50 AM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Compiler/Generation/RubyTypeBuilder.cs;Reflection @@ -36,11 +36,13 @@ TypeBuilder tb = Snippets.Shared.DefinePublicType("Ruby.Classes." + SymbolTable.IdToString(name), baseType); // make sure to generate a call to the base class constructor: + BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; + bool isDefaultCtor = true; - ConstructorInfo ci = baseType.GetConstructor(Type.EmptyTypes); - if (ci == null) { - ci = baseType.GetConstructor(_ccTypes); - if (ci == null) { + ConstructorInfo ci = baseType.GetConstructor(bindingFlags, null, Type.EmptyTypes, null); + if (ci == null || ci.IsPrivate) { + ci = baseType.GetConstructor(bindingFlags, null, _ccTypes, null); + if (ci == null || ci.IsPrivate) { throw new NotSupportedException("Can't inherit from a class without a default or code context constructor"); } isDefaultCtor = false; =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyUtils.cs;C429806 File: RubyUtils.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyUtils.cs;C429806 (server) 5/7/2008 10:19 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyUtils.cs;Reflection @@ -416,6 +416,18 @@ return null; } + public static void RequireNonClasses(params RubyModule[]/*!*/ modules) { + foreach (RubyModule module in modules) { + if (module == null) { + throw RubyExceptions.CreateTypeError("wrong argument type nil (expected Module)"); + } + + if (module.IsClass) { + throw RubyExceptions.CreateTypeError("wrong argument type Class (expected Module)"); + } + } + } + public static object Evaluate(object self, MutableString/*!*/ code, RubyScope/*!*/ targetScope, MutableString file, int line) { Assert.NotNull(code, targetScope); ===================================================================