KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > internal > runtime > methods > YARVMethod


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) 2007 Ola Bini <ola@ologix.com>
15  *
16  * Alternatively, the contents of this file may be used under the terms of
17  * either of the GNU General Public License Version 2 or later (the "GPL"),
18  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
19  * in which case the provisions of the GPL or the LGPL are applicable instead
20  * of those above. If you wish to allow use of your version of this file only
21  * under the terms of either the GPL or the LGPL, and not to allow others to
22  * use your version of this file under the terms of the CPL, indicate your
23  * decision by deleting the provisions above and replace them with the notice
24  * and other provisions required by the GPL or the LGPL. If you do not delete
25  * the provisions above, a recipient may use your version of this file under
26  * the terms of any one of the CPL, the GPL or the LGPL.
27  ***** END LICENSE BLOCK *****/

28 package org.jruby.internal.runtime.methods;
29
30 import java.util.ArrayList JavaDoc;
31 import org.jruby.Ruby;
32 import org.jruby.RubyArray;
33 import org.jruby.RubyModule;
34 import org.jruby.exceptions.JumpException;
35 import org.jruby.lexer.yacc.ISourcePosition;
36 import org.jruby.parser.StaticScope;
37 import org.jruby.runtime.Arity;
38 import org.jruby.runtime.Block;
39 import org.jruby.runtime.DynamicScope;
40 import org.jruby.runtime.ThreadContext;
41 import org.jruby.runtime.Visibility;
42 import org.jruby.runtime.builtin.IRubyObject;
43 import org.jruby.util.collections.SinglyLinkedList;
44 import org.jruby.ast.executable.YARVMachine;
45 import org.jruby.ast.executable.ISeqPosition;
46
47 /**
48  * @author <a HREF="mailto:ola.bini@ki.se">Ola Bini</a>
49  * @version $Revision: 1.2 $
50  */

51 public class YARVMethod extends DynamicMethod {
52     private SinglyLinkedList cref;
53     private YARVMachine.InstructionSequence iseq;
54     private StaticScope staticScope;
55     private Arity arity;
56
57     public YARVMethod(RubyModule implementationClass, YARVMachine.InstructionSequence iseq, StaticScope staticScope, Visibility visibility, SinglyLinkedList cref) {
58         super(implementationClass, visibility);
59         this.staticScope = staticScope;
60         this.iseq = iseq;
61         this.cref = cref;
62
63         boolean opts = iseq.args_arg_opts > 0 || iseq.args_rest > 0;
64         boolean req = iseq.args_argc > 0;
65         if(!req && !opts) {
66             this.arity = Arity.noArguments();
67         } else if(req && !opts) {
68             this.arity = Arity.fixed(iseq.args_argc);
69         } else if(opts && !req) {
70             this.arity = Arity.optional();
71         } else {
72             this.arity = Arity.required(iseq.args_argc);
73         }
74     }
75     
76     public void preMethod(ThreadContext context, RubyModule clazz, IRubyObject self, String JavaDoc name,
77             IRubyObject[] args, boolean noSuper, Block block) {
78         context.preDefMethodInternalCall(clazz, name, self, args, block, noSuper, cref, staticScope);
79     }
80     
81     public void postMethod(ThreadContext context) {
82         context.postDefMethodInternalCall();
83     }
84
85     public IRubyObject internalCall(ThreadContext context, RubyModule klazz, IRubyObject self, String JavaDoc name, IRubyObject[] args, boolean noSuper, Block block) {
86         assert args != null;
87         
88         Ruby runtime = context.getRuntime();
89         
90         try {
91             prepareArguments(context, runtime, args);
92             getArity().checkArity(runtime, args);
93
94             traceCall(context, runtime, self, name);
95
96             DynamicScope sc = new DynamicScope(staticScope,null);
97             for(int i = 0; i<args.length; i++) {
98                 sc.setValue(i,args[i],0);
99             }
100
101             return YARVMachine.INSTANCE.exec(context, self, sc, iseq.body);
102         } catch (JumpException je) {
103             if (je.getJumpType() == JumpException.JumpType.ReturnJump && je.getTarget() == this) {
104                     return (IRubyObject) je.getValue();
105             }
106             
107             throw je;
108         } finally {
109             traceReturn(context, runtime, self, name);
110         }
111     }
112
113     private void prepareArguments(ThreadContext context, Ruby runtime, IRubyObject[] args) {
114         context.setPosition(new ISeqPosition(iseq));
115
116         int expectedArgsCount = iseq.args_argc;
117         int restArg = iseq.args_rest;
118         boolean hasOptArgs = iseq.args_arg_opts > 0;
119
120         if (expectedArgsCount > args.length) {
121             throw runtime.newArgumentError("Wrong # of arguments(" + args.length + " for " + expectedArgsCount + ")");
122         }
123
124         // optArgs and restArgs require more work, so isolate them and ArrayList creation here
125
if (hasOptArgs || restArg != -1) {
126             args = prepareOptOrRestArgs(context, runtime, args, expectedArgsCount, restArg, hasOptArgs);
127         }
128         
129         context.setFrameArgs(args);
130     }
131
132     private IRubyObject[] prepareOptOrRestArgs(ThreadContext context, Ruby runtime, IRubyObject[] args, int expectedArgsCount, int restArg, boolean hasOptArgs) {
133         if (restArg == 0 && hasOptArgs) {
134             int opt = expectedArgsCount + iseq.args_arg_opts;
135
136             if (opt < args.length) {
137                 throw runtime.newArgumentError("wrong # of arguments(" + args.length + " for " + opt + ")");
138             }
139         }
140         
141         int count = expectedArgsCount + iseq.args_arg_opts + iseq.args_rest;
142
143         ArrayList JavaDoc allArgs = new ArrayList JavaDoc();
144         
145         // Combine static and optional args into a single list allArgs
146
for (int i = 0; i < count && i < args.length; i++) {
147             allArgs.add(args[i]);
148         }
149
150         if (restArg != 0) {
151             for (int i = expectedArgsCount; i < args.length; i++) {
152                 allArgs.add(args[i]);
153             }
154
155             // only set in scope if named
156
if (restArg >= 0) {
157                 RubyArray array = runtime.newArray(args.length - expectedArgsCount);
158                 for (int i = expectedArgsCount; i < args.length; i++) {
159                     array.append(args[i]);
160                 }
161
162                 context.getCurrentScope().setValue(restArg, array, 0);
163             }
164         }
165         
166         args = (IRubyObject[])allArgs.toArray(new IRubyObject[allArgs.size()]);
167         return args;
168     }
169
170     private void traceReturn(ThreadContext context, Ruby runtime, IRubyObject receiver, String JavaDoc name) {
171         if (runtime.getTraceFunction() == null) {
172             return;
173         }
174
175         ISourcePosition position = context.getPreviousFramePosition();
176         runtime.callTraceFunction(context, "return", position, receiver, name, getImplementationClass());
177     }
178
179     private void traceCall(ThreadContext context, Ruby runtime, IRubyObject receiver, String JavaDoc name) {
180         if (runtime.getTraceFunction() == null) {
181             return;
182         }
183
184         ISourcePosition position = context.getPosition();
185
186         runtime.callTraceFunction(context, "call", position, receiver, name, getImplementationClass());
187     }
188
189     public Arity getArity() {
190         return this.arity;
191     }
192     
193     public DynamicMethod dup() {
194         return new YARVMethod(getImplementationClass(), iseq, staticScope, getVisibility(), cref);
195     }
196 }// YARVMethod
197
Popular Tags