1 34 package org.jruby; 35 36 import org.jruby.exceptions.JumpException; 37 import org.jruby.runtime.Block; 38 import org.jruby.runtime.ThreadContext; 39 import org.jruby.runtime.builtin.IRubyObject; 40 41 44 public class RubyProc extends RubyObject { 45 private Block block = Block.NULL_BLOCK; 46 private RubyModule wrapper = null; 47 private boolean isLambda = false; 50 51 public RubyProc(Ruby runtime, RubyClass rubyClass) { 52 super(runtime, rubyClass); 53 } 54 55 public Block getBlock() { 56 return block; 57 } 58 59 public RubyModule getWrapper() { 60 return wrapper; 61 } 62 63 65 public static RubyProc newProc(Ruby runtime, boolean isLambda) { 66 RubyProc newProc = new RubyProc(runtime, runtime.getClass("Proc")); 67 newProc.isLambda = isLambda; 68 69 return newProc; 70 } 71 72 public IRubyObject initialize(IRubyObject[] args, Block procBlock) { 73 if (procBlock == null) { 74 throw getRuntime().newArgumentError("tried to create Proc object without a block"); 75 } 76 77 if (isLambda && procBlock == null) { 78 } 80 81 block = procBlock.cloneBlock(); 82 wrapper = getRuntime().getCurrentContext().getWrapper(); 83 block.isLambda = isLambda; 84 block.setProcObject(this); 85 86 return this; 87 } 88 89 protected IRubyObject doClone() { 90 RubyProc newProc = 91 new RubyProc(getRuntime(), getRuntime().getClass("Proc")); 92 93 newProc.block = getBlock(); 94 newProc.wrapper = getWrapper(); 95 96 return newProc; 97 } 98 99 public IRubyObject binding() { 100 return getRuntime().newBinding(block); 101 } 102 103 public IRubyObject call(IRubyObject[] args) { 104 return call(args, null, Block.NULL_BLOCK); 105 } 106 107 public IRubyObject call(IRubyObject[] args, Block unusedBlock) { 109 return call(args, null, Block.NULL_BLOCK); 110 } 111 112 public IRubyObject call(IRubyObject[] args, IRubyObject self, Block unusedBlock) { 113 assert args != null; 114 115 ThreadContext context = getRuntime().getCurrentContext(); 116 RubyModule oldWrapper = context.getWrapper(); 117 context.setWrapper(wrapper); 118 try { 119 if (block.isLambda) { 120 block.arity().checkArity(getRuntime(), args); 121 } 122 123 return block.call(context, args, self); 124 } catch (JumpException je) { 125 if (je.getJumpType() == JumpException.JumpType.BreakJump) { 126 if (block.isLambda) return (IRubyObject) je.getValue(); 127 128 throw getRuntime().newLocalJumpError("unexpected return"); 129 } else if (je.getJumpType() == JumpException.JumpType.ReturnJump) { 130 Object target = je.getTarget(); 131 133 if (target == this || block.isLambda) return (IRubyObject) je.getValue(); 134 135 if (target == null) { 136 throw getRuntime().newLocalJumpError("unexpected return"); 137 } 138 throw je; 139 } else { 140 throw je; 141 } 142 } finally { 143 context.setWrapper(oldWrapper); 144 } 145 } 146 147 public RubyFixnum arity() { 148 return getRuntime().newFixnum(block.arity().getValue()); 149 } 150 151 public RubyProc to_proc() { 152 return this; 153 } 154 } 155 | Popular Tags |