KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > ast > executable > YARVCompiledRunner


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.ast.executable;
29
30 import java.io.Reader JavaDoc;
31 import java.io.IOException JavaDoc;
32
33 import java.util.Iterator JavaDoc;
34 import java.util.List JavaDoc;
35 import java.util.Map JavaDoc;
36 import java.util.HashMap JavaDoc;
37 import java.util.IdentityHashMap JavaDoc;
38
39 import org.jruby.Ruby;
40 import org.jruby.RubyFile;
41 import org.jruby.RubyArray;
42 import org.jruby.RubyNumeric;
43 import org.jruby.RubyString;
44 import org.jruby.RubySymbol;
45 import org.jruby.parser.LocalStaticScope;
46 import org.jruby.parser.StaticScope;
47 import org.jruby.runtime.DynamicScope;
48 import org.jruby.runtime.ThreadContext;
49 import org.jruby.runtime.builtin.IRubyObject;
50
51 /**
52  * @author <a HREF="mailto:ola.bini@ki.se">Ola Bini</a>
53  */

54 public class YARVCompiledRunner {
55     private Ruby runtime;
56     private YARVMachine ym = YARVMachine.INSTANCE;
57
58     private YARVMachine.InstructionSequence iseq;
59
60     private Map JavaDoc jumps = new IdentityHashMap JavaDoc();
61     private Map JavaDoc labels = new HashMap JavaDoc();
62
63     public YARVCompiledRunner(Ruby runtime, Reader JavaDoc reader, String JavaDoc filename) {
64         this.runtime = runtime;
65         char[] first = new char[4];
66         try {
67             reader.read(first);
68             if(first[0] != 'R' || first[1] != 'B' || first[2] != 'C' || first[3] != 'M') {
69                 throw new RuntimeException JavaDoc("File is not a compiled YARV file");
70             }
71             RubyFile f = new RubyFile(runtime,filename,reader);
72             IRubyObject arr = runtime.getModule("Marshal").callMethod(runtime.getCurrentContext(),"load",f);
73             iseq = transformIntoSequence(arr);
74         } catch(IOException JavaDoc e) {
75             throw new RuntimeException JavaDoc("Couldn't read from source",e);
76         }
77     }
78
79     public YARVCompiledRunner(Ruby runtime, YARVMachine.InstructionSequence iseq) {
80         this.runtime = runtime;
81         this.iseq = iseq;
82     }
83     
84     public IRubyObject run() {
85         ThreadContext context = runtime.getCurrentContext();
86         StaticScope scope = new LocalStaticScope(null);
87         scope.setVariables(iseq.locals);
88         context.setPosition(new ISeqPosition(iseq));
89         return ym.exec(context, runtime.getObject(), new DynamicScope(scope,null), iseq.body);
90     }
91
92     private YARVMachine.InstructionSequence transformIntoSequence(IRubyObject arr) {
93         if(!(arr instanceof RubyArray)) {
94             throw new RuntimeException JavaDoc("Error when reading compiled YARV file");
95         }
96         labels.clear();
97         jumps.clear();
98
99         YARVMachine.InstructionSequence seq = new YARVMachine.InstructionSequence(runtime,null,null,null);
100         Iterator JavaDoc internal = (((RubyArray)arr).getList()).iterator();
101         seq.magic = internal.next().toString();
102         seq.major = RubyNumeric.fix2int((IRubyObject)internal.next());
103         seq.minor = RubyNumeric.fix2int((IRubyObject)internal.next());
104         seq.format_type = RubyNumeric.fix2int((IRubyObject)internal.next());
105         IRubyObject misc = (IRubyObject)internal.next();
106         if(misc.isNil()) {
107             seq.misc = null;
108         } else {
109             seq.misc = misc;
110         }
111         seq.name = internal.next().toString();
112         seq.filename = internal.next().toString();
113         seq.line = new Object JavaDoc[0]; internal.next();
114         seq.type = internal.next().toString();
115         seq.locals = toStringArray((IRubyObject)internal.next());
116         IRubyObject argo = (IRubyObject)internal.next();
117         if(argo instanceof RubyArray) {
118             List JavaDoc arglist = ((RubyArray)argo).getList();
119             seq.args_argc = RubyNumeric.fix2int((IRubyObject)arglist.get(0));
120             seq.args_arg_opts = RubyNumeric.fix2int((IRubyObject)arglist.get(1));
121             seq.args_opt_labels = toStringArray((IRubyObject)arglist.get(2));
122             seq.args_rest = RubyNumeric.fix2int((IRubyObject)arglist.get(3));
123             seq.args_block = RubyNumeric.fix2int((IRubyObject)arglist.get(4));
124         } else {
125             seq.args_argc = RubyNumeric.fix2int(argo);
126         }
127
128         seq.exception = getExceptionInformation((IRubyObject)internal.next());
129
130         List JavaDoc bodyl = ((RubyArray)internal.next()).getList();
131         YARVMachine.Instruction[] body = new YARVMachine.Instruction[bodyl.size()];
132         int real=0;
133         int i=0;
134         for(Iterator JavaDoc iter = bodyl.iterator();iter.hasNext();i++) {
135             IRubyObject is = (IRubyObject)iter.next();
136             if(is instanceof RubyArray) {
137                 body[real] = intoInstruction((RubyArray)is,real,seq);
138                 real++;
139             } else if(is instanceof RubySymbol) {
140                 labels.put(is.toString(), new Integer JavaDoc(real+1));
141             }
142         }
143         YARVMachine.Instruction[] nbody = new YARVMachine.Instruction[real];
144         System.arraycopy(body,0,nbody,0,real);
145         seq.body = nbody;
146
147         for(Iterator JavaDoc iter = jumps.keySet().iterator();iter.hasNext();) {
148             YARVMachine.Instruction k = (YARVMachine.Instruction)iter.next();
149             k.l_op0 = ((Integer JavaDoc)labels.get(jumps.get(k))).intValue() - 1;
150         }
151
152         return seq;
153     }
154
155     private String JavaDoc[] toStringArray(IRubyObject obj) {
156         if(obj.isNil()) {
157             return new String JavaDoc[0];
158         } else {
159             List JavaDoc l = ((RubyArray)obj).getList();
160             String JavaDoc[] s = new String JavaDoc[l.size()];
161             int i=0;
162             for(Iterator JavaDoc iter = l.iterator();iter.hasNext();i++) {
163                 s[i] = iter.next().toString();
164             }
165             return s;
166         }
167     }
168
169     private YARVMachine.Instruction intoInstruction(RubyArray obj, int n, YARVMachine.InstructionSequence iseq) {
170         List JavaDoc internal = obj.getList();
171         String JavaDoc name = internal.get(0).toString();
172         int instruction = YARVMachine.instruction(name);
173         YARVMachine.Instruction i = new YARVMachine.Instruction(instruction);
174         if(internal.size() > 1) {
175             IRubyObject first = (IRubyObject)internal.get(1);
176             if(instruction == YARVInstructions.GETLOCAL || instruction == YARVInstructions.SETLOCAL) {
177                 i.l_op0 = (iseq.locals.length + 1) - RubyNumeric.fix2long(first);
178             } else if(instruction == YARVInstructions.PUTOBJECT || instruction == YARVInstructions.OPT_REGEXPMATCH1 || instruction == YARVInstructions.GETINLINECACHE) {
179                 i.o_op0 = first;
180             } else if(first instanceof RubyString || first instanceof RubySymbol ) {
181                 i.s_op0 = first.toString();
182             } else if(first instanceof RubyNumeric) {
183                 i.l_op0 = RubyNumeric.fix2long(first);
184             }
185             if(instruction == YARVInstructions.SEND) {
186                 i.i_op1 = RubyNumeric.fix2int((IRubyObject)internal.get(2));
187                 i.i_op3 = RubyNumeric.fix2int((IRubyObject)internal.get(4));
188             }
189             if(instruction == YARVInstructions.DEFINEMETHOD) {
190                 i.iseq_op = transformIntoSequence((IRubyObject)internal.get(2));
191             }
192             if(isJump(instruction)) {
193                 i.index = n;
194                 jumps.put(i, internal.get(jumpIndex(instruction)).toString());
195             }
196         }
197         return i;
198     }
199
200     private boolean isJump(int i) {
201         return i == YARVInstructions.JUMP || i == YARVInstructions.BRANCHIF || i == YARVInstructions.BRANCHUNLESS ||
202             i == YARVInstructions.GETINLINECACHE || i == YARVInstructions.SETINLINECACHE;
203     }
204
205     private int jumpIndex(int i) {
206         if(i == YARVInstructions.GETINLINECACHE) {
207             return 2;
208         } else {
209             return 1;
210         }
211     }
212
213     private Object JavaDoc[] getExceptionInformation(IRubyObject obj) {
214         // System.err.println(obj.callMethod(runtime.getCurrentContext(),"inspect"));
215
return new Object JavaDoc[0];
216     }
217 }// YARVCompiledRunner
218
Popular Tags