internal RubyMethodScope(RubyScope/*!*/ parent, IAttributesCollection/*!*/ frame, RubyMethodInfo/*!*/ method, Proc blockParameter) : base(parent, frame) { _method = method; _blockParameter = blockParameter; }
[Emitted] // MethodDeclaration: public static object DefineMethod(object targetOrSelf, RubyScope/*!*/ scope, RubyMethodBody/*!*/ body) { Assert.NotNull(body, scope); RubyModule instanceOwner, singletonOwner; RubyMemberFlags instanceFlags, singletonFlags; bool moduleFunction = false; if (body.HasTarget) { if (!RubyUtils.CanCreateSingleton(targetOrSelf)) { throw RubyExceptions.CreateTypeError("can't define singleton method for literals"); } instanceOwner = null; instanceFlags = RubyMemberFlags.Invalid; singletonOwner = scope.RubyContext.CreateSingletonClass(targetOrSelf); singletonFlags = RubyMemberFlags.Public; } else { var attributesScope = scope.GetMethodAttributesDefinitionScope(); if ((attributesScope.MethodAttributes & RubyMethodAttributes.ModuleFunction) == RubyMethodAttributes.ModuleFunction) { // Singleton module-function's scope points to the instance method's RubyMemberInfo. // This affects: // 1) super call // Super call is looking for Method.DeclaringModule while searching MRO, which would fail if the singleton module-function // was in MRO. Since module-function can only be used on module the singleton method could only be on module's singleton. // Module's singleton is never part of MRO so we are safe. // 2) trace // Method call trace reports non-singleton module. // MRI 1.8: instance method owner is self -> it is possible (via define_method) to define m.f. on a class (bug) // MRI 1.9: instance method owner GetMethodDefinitionOwner // MRI allows to define m.f. on classes but then doesn't work correctly with it. instanceOwner = scope.GetMethodDefinitionOwner(); if (instanceOwner.IsClass) { throw RubyExceptions.CreateTypeError("A module function cannot be defined on a class."); } instanceFlags = RubyMemberFlags.Private; singletonOwner = instanceOwner.SingletonClass; singletonFlags = RubyMemberFlags.Public; moduleFunction = true; } else { instanceOwner = scope.GetMethodDefinitionOwner(); instanceFlags = (RubyMemberFlags)RubyUtils.GetSpecialMethodVisibility(attributesScope.Visibility, body.Name); singletonOwner = null; singletonFlags = RubyMemberFlags.Invalid; } } RubyMethodInfo instanceMethod = null, singletonMethod = null; if (instanceOwner != null) { SetMethod(scope.RubyContext, instanceMethod = new RubyMethodInfo(body, scope, instanceOwner, instanceFlags) ); } if (singletonOwner != null) { SetMethod(scope.RubyContext, singletonMethod = new RubyMethodInfo(body, scope, singletonOwner, singletonFlags) ); } // the method's scope saves the result => singleton module-function uses instance-method var method = instanceMethod ?? singletonMethod; method.DeclaringModule.MethodAdded(body.Name); if (moduleFunction) { Debug.Assert(!method.DeclaringModule.IsClass); method.DeclaringModule.SingletonClass.MethodAdded(body.Name); } return null; }
private static void SetMethod(RubyContext/*!*/ callerContext, RubyMethodInfo/*!*/ method) { var owner = method.DeclaringModule; // Do not trigger the add-method event just yet, we need to assign the result into closure before executing any user code. // If the method being defined is "method_added" itself, we would call that method before the info gets assigned to the closure. owner.SetMethodNoEvent(callerContext, method.DefinitionName, method); // expose RubyMethod in the scope (the method is bound to the main singleton instance): if (owner.GlobalScope != null) { owner.GlobalScope.Scope.SetName( SymbolTable.StringToId(method.DefinitionName), new RubyMethod(owner.GlobalScope.MainObject, method, method.DefinitionName) ); } }
internal RubyMethodScope(RubyScope/*!*/ parent, RubyMethodInfo/*!*/ method, Proc blockParameter, RuntimeFlowControl/*!*/ runtimeFlowControl, object selfObject) : base(parent, runtimeFlowControl, selfObject) { _method = method; _blockParameter = blockParameter; MethodAttributes = RubyMethodAttributes.PublicInstance; }
public static object MethodDefined(RubyMethodInfo/*!*/ method) { method.Context.MethodAdded(method.DeclaringModule, method.DefinitionName); if (method.IsModuleFunction) { Debug.Assert(!method.DeclaringModule.IsClass); method.Context.MethodAdded(method.DeclaringModule.SingletonClass, method.DefinitionName); } return null; }
[Emitted] // MethodDeclaration: public static RubyMethodInfo/*!*/ DefineMethod(object targetOrSelf, object/*!*/ ast, RubyScope/*!*/ scope, bool hasTarget, string/*!*/ name, Delegate/*!*/ clrMethod, int mandatory, int optional, bool hasUnsplatParameter) { Assert.NotNull(ast, scope, clrMethod, name); RubyModule instanceOwner, singletonOwner; RubyMemberFlags instanceFlags, singletonFlags; if (hasTarget) { if (!RubyUtils.CanCreateSingleton(targetOrSelf)) { throw RubyExceptions.CreateTypeError("can't define singleton method for literals"); } instanceOwner = null; instanceFlags = RubyMemberFlags.Invalid; singletonOwner = scope.RubyContext.CreateSingletonClass(targetOrSelf); singletonFlags = RubyMemberFlags.Public; } else { // TODO: ??? var attributesScope = scope.GetMethodAttributesDefinitionScope(); //var attributesScope = scope; if ((attributesScope.MethodAttributes & RubyMethodAttributes.ModuleFunction) == RubyMethodAttributes.ModuleFunction) { // Singleton module-function's scope points to the instance method's RubyMemberInfo. // This affects: // 1) super call // Super call is looking for Method.DeclaringModule while searching MRO, which would fail if the singleton module-function // was in MRO. Since module-function can only be used on module the singleton method could only be on module's singleton. // Module's singleton is never part of MRO so we are safe. // 2) trace // Method call trace reports non-singleton module. // MRI 1.8: instance method owner is self -> it is possible (via define_method) to define m.f. on a class (bug) // MRI 1.9: instance method owner GetMethodDefinitionOwner // MRI allows to define m.f. on classes but then doesn't work correctly with it. instanceOwner = scope.GetMethodDefinitionOwner(); if (instanceOwner.IsClass) { throw RubyExceptions.CreateTypeError("A module function cannot be defined on a class."); } instanceFlags = RubyMemberFlags.ModuleFunction | RubyMemberFlags.Private; singletonOwner = instanceOwner.SingletonClass; singletonFlags = RubyMemberFlags.ModuleFunction | RubyMemberFlags.Public; } else { instanceOwner = scope.GetMethodDefinitionOwner(); instanceFlags = (RubyMemberFlags)RubyUtils.GetSpecialMethodVisibility(attributesScope.Visibility, name); singletonOwner = null; singletonFlags = RubyMemberFlags.Invalid; } } RubyMethodInfo instanceMethod = null, singletonMethod = null; if (instanceOwner != null) { SetMethod(scope.RubyContext, instanceMethod = new RubyMethodInfo(ast, clrMethod, instanceOwner, name, mandatory, optional, hasUnsplatParameter, instanceFlags) ); } if (singletonOwner != null) { SetMethod(scope.RubyContext, singletonMethod = new RubyMethodInfo(ast, clrMethod, singletonOwner, name, mandatory, optional, hasUnsplatParameter, singletonFlags) ); } // the method's scope saves the result => singleton module-function uses instance-method return instanceMethod ?? singletonMethod; }
public static RubyMethodScope/*!*/ CreateMethodScope(LocalsDictionary/*!*/ locals, RubyScope/*!*/ parent, RubyMethodInfo/*!*/ methodDefinition, RuntimeFlowControl/*!*/ rfc, object selfObject, Proc blockParameter) { Assert.NotNull(locals, parent, methodDefinition, rfc); RubyMethodScope scope = new RubyMethodScope(parent, locals, methodDefinition, blockParameter); scope.Initialize(rfc, RubyMethodAttributes.PublicInstance, selfObject); scope.SetDebugName("method " + methodDefinition.DefinitionName + ((blockParameter != null) ? "&" : null) ); return scope; }
public static RubyMethodScope/*!*/ CreateMethodScope(LocalsDictionary/*!*/ locals, RubyScope/*!*/ parent, RubyMethodInfo/*!*/ methodDefinition, RuntimeFlowControl/*!*/ rfc, object selfObject, Proc blockParameter) { RubyMethodScope scope = new RubyMethodScope(parent, methodDefinition, blockParameter, rfc, selfObject); scope.SetDebugName("method " + methodDefinition.DefinitionName + ((blockParameter != null) ? "&" : null)); scope.Frame = locals; return scope; }