1 29 package org.jruby; 30 31 import org.jruby.internal.runtime.methods.DynamicMethod; 32 import org.jruby.runtime.Block; 33 import org.jruby.runtime.CallbackFactory; 34 import org.jruby.runtime.ObjectAllocator; 35 import org.jruby.runtime.builtin.IRubyObject; 36 37 43 public class RubyUnboundMethod extends RubyMethod { 44 protected RubyUnboundMethod(Ruby runtime) { 45 super(runtime, runtime.getClass("UnboundMethod")); 46 } 47 48 public static RubyUnboundMethod newUnboundMethod( 49 RubyModule implementationModule, 50 String methodName, 51 RubyModule originModule, 52 String originName, 53 DynamicMethod method) { 54 RubyUnboundMethod newMethod = new RubyUnboundMethod(implementationModule.getRuntime()); 55 56 newMethod.implementationModule = implementationModule; 57 newMethod.methodName = methodName; 58 newMethod.originModule = originModule; 59 newMethod.originName = originName; 60 newMethod.method = method; 61 62 return newMethod; 63 } 64 65 public static RubyClass defineUnboundMethodClass(Ruby runtime) { 66 RubyClass newClass = 68 runtime.defineClass("UnboundMethod", runtime.getClass("Method"), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR); 69 70 CallbackFactory callbackFactory = runtime.callbackFactory(RubyUnboundMethod.class); 71 newClass.defineMethod("[]", callbackFactory.getOptMethod("call")); 72 newClass.defineMethod("bind", callbackFactory.getMethod("bind", RubyKernel.IRUBY_OBJECT)); 73 newClass.defineMethod("call", callbackFactory.getOptMethod("call")); 74 newClass.defineMethod("to_proc", callbackFactory.getMethod("to_proc")); 75 newClass.defineMethod("unbind", callbackFactory.getMethod("unbind")); 76 77 return newClass; 78 } 79 80 83 public IRubyObject call(IRubyObject[] args, Block block) { 84 throw getRuntime().newTypeError("you cannot call unbound method; bind first"); 85 } 86 87 90 public RubyUnboundMethod unbind(Block block) { 91 return this; 92 } 93 94 public RubyMethod bind(IRubyObject aReceiver, Block block) { 95 RubyClass receiverClass = aReceiver.getMetaClass(); 96 97 if (!aReceiver.isKindOf(originModule)) { 98 if (originModule instanceof MetaClass) { 99 throw getRuntime().newTypeError("singleton method called for a different object"); 100 } else if (receiverClass instanceof MetaClass && receiverClass.getMethods().containsKey(originName)) { 101 throw getRuntime().newTypeError("method `" + originName + "' overridden"); 102 } else if ( 103 !(originModule.isModule() ? aReceiver.isKindOf(originModule) : aReceiver.getType() == originModule)) { 104 throw getRuntime().newTypeError("bind argument must be an instance of " + originModule.getName()); 106 } 107 } 108 return RubyMethod.newMethod(implementationModule, methodName, receiverClass, originName, method, aReceiver); 109 } 110 } 111 | Popular Tags |