1 32 package org.jruby; 33 34 import org.jruby.exceptions.JumpException; 35 import org.jruby.internal.runtime.methods.DynamicMethod; 36 import org.jruby.internal.runtime.methods.IterateCallable; 37 import org.jruby.runtime.Block; 38 import org.jruby.runtime.CallbackFactory; 39 import org.jruby.runtime.ObjectAllocator; 40 import org.jruby.runtime.ThreadContext; 41 import org.jruby.runtime.builtin.IRubyObject; 42 43 53 public class RubyMethod extends RubyObject { 54 protected RubyModule implementationModule; 55 protected String methodName; 56 protected RubyModule originModule; 57 protected String originName; 58 protected DynamicMethod method; 59 protected IRubyObject receiver; 60 61 protected RubyMethod(Ruby runtime, RubyClass rubyClass) { 62 super(runtime, rubyClass); 63 } 64 65 68 public static RubyClass createMethodClass(Ruby runtime) { 69 RubyClass methodClass = runtime.defineClass("Method", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR); 71 72 CallbackFactory callbackFactory = runtime.callbackFactory(RubyMethod.class); 73 74 methodClass.defineFastMethod("arity", callbackFactory.getFastMethod("arity")); 75 methodClass.defineMethod("to_proc", callbackFactory.getMethod("to_proc")); 76 methodClass.defineMethod("unbind", callbackFactory.getMethod("unbind")); 77 methodClass.defineMethod("call", callbackFactory.getOptMethod("call")); 78 methodClass.defineMethod("[]", callbackFactory.getOptMethod("call")); 79 methodClass.defineFastMethod("inspect", callbackFactory.getFastMethod("inspect")); 80 methodClass.defineFastMethod("to_s", callbackFactory.getFastMethod("inspect")); 81 82 return methodClass; 83 } 84 85 public static RubyMethod newMethod( 86 RubyModule implementationModule, 87 String methodName, 88 RubyModule originModule, 89 String originName, 90 DynamicMethod method, 91 IRubyObject receiver) { 92 Ruby runtime = implementationModule.getRuntime(); 93 RubyMethod newMethod = new RubyMethod(runtime, runtime.getClass("Method")); 94 95 newMethod.implementationModule = implementationModule; 96 newMethod.methodName = methodName; 97 newMethod.originModule = originModule; 98 newMethod.originName = originName; 99 newMethod.method = method; 100 newMethod.receiver = receiver; 101 102 return newMethod; 103 } 104 105 108 public IRubyObject call(IRubyObject[] args, Block block) { 109 assert args != null; 110 ThreadContext tc = getRuntime().getCurrentContext(); 111 112 method.getArity().checkArity(getRuntime(), args); 113 114 return method.call(tc, receiver, implementationModule, methodName, args, false, block); 116 } 117 118 122 public RubyFixnum arity() { 123 return getRuntime().newFixnum(method.getArity().getValue()); 124 } 125 126 129 public IRubyObject to_proc(Block unusedBlock) { 130 CallbackFactory f = getRuntime().callbackFactory(RubyMethod.class); 131 Ruby r = getRuntime(); 132 ThreadContext tc = r.getCurrentContext(); 133 Block block = Block.createBlock(tc, null, tc.getCurrentScope().cloneScope(), 134 new IterateCallable(f.getBlockMethod("bmcall"), this), r.getTopSelf()); 135 136 while (true) { 137 try { 138 return f.getSingletonMethod("mproc").execute(getRuntime().getNil(), 140 IRubyObject.NULL_ARRAY, block); 141 } catch (JumpException je) { 142 if (je.getJumpType() == JumpException.JumpType.BreakJump) { 143 return (IRubyObject) je.getValue(); 144 } else if (je.getJumpType() == JumpException.JumpType.ReturnJump) { 145 return (IRubyObject) je.getTarget(); 146 } else if (je.getJumpType() == JumpException.JumpType.RetryJump) { 147 } else { 149 throw je; 150 } 151 } 152 } 153 } 154 155 160 public static IRubyObject mproc(IRubyObject recv, Block block) { 161 Ruby runtime = recv.getRuntime(); 162 ThreadContext tc = runtime.getCurrentContext(); 163 164 tc.preMproc(); 165 166 try { 167 return RubyKernel.proc(recv, block); 168 } finally { 169 tc.postMproc(); 170 } 171 } 172 173 178 public static IRubyObject bmcall(IRubyObject blockArg, IRubyObject arg1, IRubyObject self, Block unusedBlock) { 179 if (blockArg instanceof RubyArray) { 180 return ((RubyMethod) arg1).call(((RubyArray) blockArg).toJavaArray(), Block.NULL_BLOCK); 182 } 183 return ((RubyMethod) arg1).call(new IRubyObject[] { blockArg }, Block.NULL_BLOCK); 185 } 186 187 public RubyUnboundMethod unbind(Block unusedBlock) { 188 RubyUnboundMethod unboundMethod = 189 RubyUnboundMethod.newUnboundMethod(implementationModule, methodName, originModule, originName, method); 190 unboundMethod.receiver = this; 191 unboundMethod.infectBy(this); 192 193 return unboundMethod; 194 } 195 196 public IRubyObject inspect() { 197 String cname = getMetaClass().getRealClass().getName(); 198 RubyString str = getRuntime().newString("#<" + cname + ": " + originModule.getName() + "#" + methodName + ">"); 199 str.setTaint(isTaint()); 200 return str; 201 } 202 } 203 204 | Popular Tags |