KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > RubyProc


1 /***** BEGIN LICENSE BLOCK *****
2  * Version: CPL 1.0/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Common Public
5  * License Version 1.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of
7  * the License at http://www.eclipse.org/legal/cpl-v10.html
8  *
9  * Software distributed under the License is distributed on an "AS
10  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * rights and limitations under the License.
13  *
14  * Copyright (C) 2001 Chad Fowler <chadfowler@chadfowler.com>
15  * Copyright (C) 2001 Alan Moore <alan_moore@gmx.net>
16  * Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
17  * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
18  * Copyright (C) 2002-2005 Thomas E Enebo <enebo@acm.org>
19  * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
20  * Copyright (C) 2005 Charles O Nutter <headius@headius.com>
21  *
22  * Alternatively, the contents of this file may be used under the terms of
23  * either of the GNU General Public License Version 2 or later (the "GPL"),
24  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
25  * in which case the provisions of the GPL or the LGPL are applicable instead
26  * of those above. If you wish to allow use of your version of this file only
27  * under the terms of either the GPL or the LGPL, and not to allow others to
28  * use your version of this file under the terms of the CPL, indicate your
29  * decision by deleting the provisions above and replace them with the notice
30  * and other provisions required by the GPL or the LGPL. If you do not delete
31  * the provisions above, a recipient may use your version of this file under
32  * the terms of any one of the CPL, the GPL or the LGPL.
33  ***** END LICENSE BLOCK *****/

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 /**
42  * @author jpetersen
43  */

44 public class RubyProc extends RubyObject {
45     private Block block = Block.NULL_BLOCK;
46     private RubyModule wrapper = null;
47     // FIXME: I added it here since I wanted initialize to deal with it and not newProc. I could
48
// be wrong and I suspect we can find a better way of dealing with this.
49
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     // Proc class
64

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             // TODO: warn "tried to create Proc object without a block"
79
}
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     // ENEBO: For method def others are Java to java versions
108
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 JavaDoc target = je.getTarget();
131                 //System.out.println("TARGET: " + target);
132

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