Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

590
LINES

< > BotCompany Repo | #1000249 // LuaClosure.java

Java source code

1  
/*******************************************************************************
2  
* Copyright (c) 2009 Luaj.org. All rights reserved.
3  
*
4  
* Permission is hereby granted, free of charge, to any person obtaining a copy
5  
* of this software and associated documentation files (the "Software"), to deal
6  
* in the Software without restriction, including without limitation the rights
7  
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  
* copies of the Software, and to permit persons to whom the Software is
9  
* furnished to do so, subject to the following conditions:
10  
*
11  
* The above copyright notice and this permission notice shall be included in
12  
* all copies or substantial portions of the Software.
13  
* 
14  
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  
* THE SOFTWARE.
21  
******************************************************************************/
22  
package org.luaj.vm2;
23  
24  
import net.luaos.tb.common.LuaUtil;
25  
26  
/**
27  
 * Central interpreter loop
28  
 *
29  
 * Extension of {@link LuaFunction} which executes lua bytecode. 
30  
 * <p>
31  
 * A {@link LuaClosure} is a combination of a {@link Prototype} 
32  
 * and a {@link LuaValue} to use as an environment for execution. 
33  
 * <p>
34  
 * There are three main ways {@link LuaClosure} instances are created:
35  
 * <ul> 
36  
 * <li>Construct an instance using {@link #LuaClosure(Prototype, LuaValue)}</li>
37  
 * <li>Construct it indirectly by loading a chunk via {@link LuaCompiler#load(java.io.InputStream, String, LuaValue)}
38  
 * <li>Execute the lua bytecode {@link Lua#OP_CLOSURE} as part of bytecode processing
39  
 * </ul>
40  
 * <p>
41  
 * To construct it directly, the {@link Prototype} is typically created via a compiler such as {@link LuaC}:
42  
 * <pre> {@code
43  
 * InputStream is = new ByteArrayInputStream("print('hello,world').getBytes());
44  
 * Prototype p = LuaC.instance.compile(is, "script");
45  
 * LuaValue _G = JsePlatform.standardGlobals()
46  
 * LuaClosure f = new LuaClosure(p, _G);
47  
 * }</pre> 
48  
 * <p>
49  
 * To construct it indirectly, the {@link LuaC} compiler may be used, 
50  
 * which implements the {@link LuaCompiler} interface: 
51  
 * <pre> {@code
52  
 * LuaFunction f = LuaC.instance.load(is, "script", _G);
53  
 * }</pre>
54  
 * <p>
55  
 * Typically, a closure that has just been loaded needs to be initialized by executing it, 
56  
 * and its return value can be saved if needed:
57  
 * <pre> {@code
58  
 * LuaValue r = f.call();
59  
 * _G.set( "mypkg", r ) 
60  
 * }</pre>
61  
 * <p> 
62  
 * In the preceding, the loaded value is typed as {@link LuaFunction} 
63  
 * to allow for the possibility of other compilers such as {@link LuaJC}
64  
 * producing {@link LuaFunction} directly without 
65  
 * creating a {@link Prototype} or {@link LuaClosure}.
66  
 * <p> 
67  
 * Since a {@link LuaClosure} is a {@link LuaFunction} which is a {@link LuaValue}, 
68  
 * all the value operations can be used directly such as:
69  
 * <ul>
70  
 * <li>{@link LuaValue#call()}</li>
71  
 * <li>{@link LuaValue#call(LuaValue)}</li>
72  
 * <li>{@link LuaValue#invoke()}</li>
73  
 * <li>{@link LuaValue#invoke(Varargs)}</li>
74  
 * <li>{@link LuaValue#method(String)}</li>
75  
 * <li>{@link LuaValue#method(String,LuaValue)}</li>
76  
 * <li>{@link LuaValue#invokemethod(String)}</li>
77  
 * <li>{@link LuaValue#invokemethod(String,Varargs)}</li>
78  
 * <li> ...</li> 
79  
 * </ul>
80  
 * @see LuaValue
81  
 * @see LuaFunction
82  
 * @see LuaValue#isclosure()
83  
 * @see LuaValue#checkclosure()
84  
 * @see LuaValue#optclosure(LuaClosure)
85  
 * @see LoadState
86  
 * @see LoadState#compiler
87  
 */
88  
public class LuaClosure extends LuaFunction {
89  
	private static final UpValue[] NOUPVALUES = new UpValue[0];
90  
	
91  
	public final Prototype p;
92  
93  
	public UpValue[] upValues;
94  
	
95  
	Globals globals;
96  
	
97  
	/** Create a closure around a Prototype with a specific environment.
98  
	 * If the prototype has upvalues, the environment will be written into the first upvalue.
99  
	 * @param p the Prototype to construct this Closure for. 
100  
	 * @param env the environment to associate with the closure.
101  
	 */
102  
	public LuaClosure(Prototype p, LuaValue env) {
103  
    this(p, env, env instanceof Globals? (Globals) env: null);
104  
  }
105  
106  
  public LuaClosure(Prototype p, LuaValue env, Globals globals) {
107  
		this.p = p;
108  
		if (p.upvalues == null || p.upvalues.length == 0)
109  
			this.upValues = NOUPVALUES;
110  
		else {
111  
			this.upValues = new UpValue[p.upvalues.length];
112  
			this.upValues[0] = new UpValue(new LuaValue[] {env}, 0);
113  
		}
114  
		this.globals = globals;
115  
116  
    // XXX Stefan
117  
    if (globals == null)
118  
      throw new RuntimeException("Fatal: Closure has no globals.");
119  
	}
120  
	
121  
	public boolean isclosure() {
122  
		return true;
123  
	}
124  
	
125  
	public LuaClosure optclosure(LuaClosure defval) {
126  
		return this;
127  
	}
128  
129  
	public LuaClosure checkclosure() {
130  
		return this;
131  
	}
132  
	
133  
	public LuaValue getmetatable() { 
134  
		return s_metatable; 
135  
	}
136  
	
137  
	public String tojstring() {
138  
		return "function: " + p.toString();
139  
	}
140  
	
141  
	public final LuaValue call() {
142  
		LuaValue[] stack = new LuaValue[p.maxstacksize];
143  
		for (int i = 0; i < p.numparams; ++i )
144  
			stack[i] = NIL;
145  
		return execute(stack,NONE).arg1();
146  
	}
147  
148  
	public final LuaValue call(LuaValue arg) {
149  
		LuaValue[] stack = new LuaValue[p.maxstacksize];
150  
		System.arraycopy(NILS, 0, stack, 0, p.maxstacksize);
151  
		for (int i = 1; i < p.numparams; ++i )
152  
			stack[i] = NIL;
153  
		switch ( p.numparams ) {
154  
		default: stack[0]=arg; return execute(stack,NONE).arg1();
155  
		case 0: return execute(stack,arg).arg1();
156  
		}
157  
	}
158  
	
159  
	public final LuaValue call(LuaValue arg1, LuaValue arg2) {
160  
		LuaValue[] stack = new LuaValue[p.maxstacksize];
161  
		for (int i = 2; i < p.numparams; ++i )
162  
			stack[i] = NIL;
163  
		switch ( p.numparams ) {
164  
		default: stack[0]=arg1; stack[1]=arg2; return execute(stack,NONE).arg1();
165  
		case 1: stack[0]=arg1; return execute(stack,arg2).arg1();
166  
		case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2): NONE).arg1();
167  
		}
168  
	}
169  
170  
	public final LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
171  
		LuaValue[] stack = new LuaValue[p.maxstacksize];
172  
		for (int i = 3; i < p.numparams; ++i )
173  
			stack[i] = NIL;
174  
		switch ( p.numparams ) {
175  
		default: stack[0]=arg1; stack[1]=arg2; stack[2]=arg3; return execute(stack,NONE).arg1();
176  
		case 2: stack[0]=arg1; stack[1]=arg2; return execute(stack,arg3).arg1();
177  
		case 1: stack[0]=arg1; return execute(stack,p.is_vararg!=0? varargsOf(arg2,arg3): NONE).arg1();
178  
		case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2,arg3): NONE).arg1();
179  
		}
180  
	}
181  
182  
	public final Varargs invoke(Varargs varargs) {
183  
		return onInvoke(varargs).eval();
184  
	}
185  
	
186  
	public final Varargs onInvoke(Varargs varargs) {
187  
		LuaValue[] stack = new LuaValue[p.maxstacksize];
188  
		for ( int i=0; i<p.numparams; i++ )
189  
			stack[i] = varargs.arg(i+1);		
190  
		return execute(stack,p.is_vararg!=0? varargs.subargs(p.numparams+1): NONE);
191  
	}
192  
	
193  
	protected Varargs execute( LuaValue[] stack, Varargs varargs ) {
194  
		// loop through instructions
195  
		int i,a,b,c,pc=0,top=0;
196  
		LuaValue o;
197  
		Varargs v = NONE;
198  
		int[] code = p.code;
199  
		LuaValue[] k = p.k;
200  
201  
    if (LuaUtil.verbose)
202  
      System.out.println("LuaClosure.execute, globals.running=" + globals.running);
203  
204  
    // upvalues are only possible when closures create closures
205  
		// TODO: use linked list.
206  
		UpValue[] openups = p.p.length>0? new UpValue[stack.length]: null;
207  
		
208  
		// allow for debug hooks
209  
		if (globals != null && globals.debuglib != null)
210  
			globals.debuglib.onCall( this, varargs, stack ); 
211  
212  
		// process instructions
213  
		try {
214  
			while ( true ) {
215  
				if (globals != null && globals.debuglib != null)
216  
					globals.debuglib.onInstruction( pc, v, top ); 
217  
				
218  
				// pull out instruction
219  
				i = code[pc++];
220  
				a = ((i>>6) & 0xff);
221  
				
222  
				// process the op code
223  
				switch ( i & 0x3f ) {
224  
				
225  
				case Lua.OP_MOVE:/*	A B	R(A):= R(B)					*/
226  
					stack[a] = stack[i>>>23];
227  
					continue;
228  
					
229  
				case Lua.OP_LOADK:/*	A Bx	R(A):= Kst(Bx)					*/
230  
					stack[a] = k[i>>>14];
231  
					continue;
232  
					
233  
				case Lua.OP_LOADBOOL:/*	A B C	R(A):= (Bool)B: if (C) pc++			*/
234  
	                stack[a] = (i>>>23!=0)? LuaValue.TRUE: LuaValue.FALSE;
235  
	                if ((i&(0x1ff<<14)) != 0)
236  
	                    pc++; /* skip next instruction (if C) */
237  
	                continue;
238  
	
239  
				case Lua.OP_LOADNIL: /*	A B	R(A):= ...:= R(A+B):= nil			*/
240  
					for ( b=i>>>23; b-->=0; )
241  
						stack[a++] = LuaValue.NIL;
242  
					continue;
243  
					
244  
				case Lua.OP_GETUPVAL: /*	A B	R(A):= UpValue[B]				*/
245  
	                stack[a] = upValues[i>>>23].getValue();
246  
	                continue;
247  
					
248  
				case Lua.OP_GETTABUP: /*	A B C	R(A) := UpValue[B][RK(C)]			*/
249  
					stack[a] = upValues[i>>>23].getValue().get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
250  
					continue;
251  
	                
252  
				case Lua.OP_GETTABLE: /*	A B C	R(A):= R(B)[RK(C)]				*/
253  
	                stack[a] = stack[i>>>23].get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
254  
					continue;
255  
					
256  
				case Lua.OP_SETTABUP: /*	A B C	UpValue[A][RK(B)] := RK(C)			*/
257  
	                upValues[a].getValue().set(((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]), (c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
258  
					continue;
259  
					
260  
				case Lua.OP_SETUPVAL: /*	A B	UpValue[B]:= R(A)				*/
261  
					upValues[i>>>23].setValue(stack[a]);
262  
					continue;
263  
					
264  
				case Lua.OP_SETTABLE: /*	A B C	R(A)[RK(B)]:= RK(C)				*/
265  
					stack[a].set(((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]), (c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
266  
					continue;
267  
					
268  
				case Lua.OP_NEWTABLE: /*	A B C	R(A):= {} (size = B,C)				*/
269  
					stack[a] = new LuaTable(i>>>23,(i>>14)&0x1ff);
270  
					continue;
271  
					
272  
				case Lua.OP_SELF: /*	A B C	R(A+1):= R(B): R(A):= R(B)[RK(C)]		*/
273  
					stack[a+1] = (o = stack[i>>>23]);
274  
					stack[a] = o.get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
275  
					continue;
276  
					
277  
				case Lua.OP_ADD: /*	A B C	R(A):= RK(B) + RK(C)				*/
278  
					stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).add((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
279  
					continue;
280  
					
281  
				case Lua.OP_SUB: /*	A B C	R(A):= RK(B) - RK(C)				*/
282  
					stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).sub((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
283  
					continue;
284  
					
285  
				case Lua.OP_MUL: /*	A B C	R(A):= RK(B) * RK(C)				*/
286  
					stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mul((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
287  
					continue;
288  
					
289  
				case Lua.OP_DIV: /*	A B C	R(A):= RK(B) / RK(C)				*/
290  
					stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).div((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
291  
					continue;
292  
					
293  
				case Lua.OP_MOD: /*	A B C	R(A):= RK(B) % RK(C)				*/
294  
					stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mod((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
295  
					continue;
296  
					
297  
				case Lua.OP_POW: /*	A B C	R(A):= RK(B) ^ RK(C)				*/
298  
					stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).pow((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
299  
					continue;
300  
					
301  
				case Lua.OP_UNM: /*	A B	R(A):= -R(B)					*/
302  
					stack[a] = stack[i>>>23].neg();
303  
					continue;
304  
					
305  
				case Lua.OP_NOT: /*	A B	R(A):= not R(B)				*/
306  
					stack[a] = stack[i>>>23].not();
307  
					continue;
308  
					
309  
				case Lua.OP_LEN: /*	A B	R(A):= length of R(B)				*/
310  
					stack[a] = stack[i>>>23].len();
311  
					continue;
312  
					
313  
				case Lua.OP_CONCAT: /*	A B C	R(A):= R(B).. ... ..R(C)			*/
314  
					b = i>>>23;
315  
					c = (i>>14)&0x1ff;
316  
					{
317  
						if ( c > b+1 ) {
318  
							Buffer sb = stack[c].buffer();
319  
							while ( --c>=b ) 
320  
								sb = stack[c].concat(sb);
321  
							stack[a] = sb.value();
322  
						} else {
323  
							stack[a] = stack[c-1].concat(stack[c]);
324  
						}
325  
					}
326  
					continue;
327  
					
328  
				case Lua.OP_JMP: /*	sBx	pc+=sBx					*/
329  
					pc  += (i>>>14)-0x1ffff;
330  
					if (a > 0) {
331  
						for (--a, b = openups.length; --b>=0; )
332  
							if (openups[b] != null && openups[b].index >= a) {
333  
								openups[b].close();
334  
								openups[b] = null;
335  
							}
336  
					}
337  
					continue;
338  
					
339  
				case Lua.OP_EQ: /*	A B C	if ((RK(B) == RK(C)) ~= A) then pc++		*/
340  
					if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).eq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) ) 
341  
						++pc;
342  
					continue;
343  
					
344  
				case Lua.OP_LT: /*	A B C	if ((RK(B) <  RK(C)) ~= A) then pc++  		*/
345  
					if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lt_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) ) 
346  
						++pc;
347  
					continue;
348  
					
349  
				case Lua.OP_LE: /*	A B C	if ((RK(B) <= RK(C)) ~= A) then pc++  		*/
350  
					if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lteq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) ) 
351  
						++pc;
352  
					continue;
353  
					
354  
				case Lua.OP_TEST: /*	A C	if not (R(A) <=> C) then pc++			*/ 
355  
					if ( stack[a].toboolean() != ((i&(0x1ff<<14))!=0) ) 
356  
						++pc;
357  
					continue;
358  
					
359  
				case Lua.OP_TESTSET: /*	A B C	if (R(B) <=> C) then R(A):= R(B) else pc++	*/
360  
					/* note: doc appears to be reversed */
361  
					if ( (o=stack[i>>>23]).toboolean() != ((i&(0x1ff<<14))!=0) ) 
362  
						++pc;
363  
					else
364  
						stack[a] = o; // TODO: should be sBx? 
365  
					continue;
366  
					
367  
				case Lua.OP_CALL: /*	A B C	R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */
368  
					switch ( i & (Lua.MASK_B | Lua.MASK_C) ) {
369  
					case (1<<Lua.POS_B) | (0<<Lua.POS_C): v=stack[a].invoke(NONE); top=a+v.narg(); continue;
370  
					case (2<<Lua.POS_B) | (0<<Lua.POS_C): v=stack[a].invoke(stack[a+1]); top=a+v.narg(); continue;
371  
					case (1<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(); continue;
372  
					case (2<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(stack[a+1]); continue;
373  
					case (3<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(stack[a+1],stack[a+2]); continue;
374  
					case (4<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(stack[a+1],stack[a+2],stack[a+3]); continue;
375  
					case (1<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(); continue;
376  
					case (2<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(stack[a+1]); continue;
377  
					case (3<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(stack[a+1],stack[a+2]); continue;
378  
					case (4<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(stack[a+1],stack[a+2],stack[a+3]); continue;
379  
					default:
380  
						b = i>>>23;
381  
						c = (i>>14)&0x1ff;
382  
						v = b>0? 
383  
							varargsOf(stack,a+1,b-1): // exact arg count
384  
							varargsOf(stack, a+1, top-v.narg()-(a+1), v); // from prev top 
385  
						v = stack[a].invoke(v);
386  
						if ( c > 0 ) {
387  
							while ( --c > 0 )
388  
								stack[a+c-1] = v.arg(c);
389  
							v = NONE; // TODO: necessary?
390  
						} else {
391  
							top = a + v.narg();
392  
						}
393  
						continue;
394  
					}
395  
					
396  
				case Lua.OP_TAILCALL: /*	A B C	return R(A)(R(A+1), ... ,R(A+B-1))		*/
397  
					switch ( i & Lua.MASK_B ) {
398  
					case (1<<Lua.POS_B): return new TailcallVarargs(stack[a], NONE);
399  
					case (2<<Lua.POS_B): return new TailcallVarargs(stack[a], stack[a+1]);
400  
					case (3<<Lua.POS_B): return new TailcallVarargs(stack[a], varargsOf(stack[a+1],stack[a+2]));
401  
					case (4<<Lua.POS_B): return new TailcallVarargs(stack[a], varargsOf(stack[a+1],stack[a+2],stack[a+3]));
402  
					default:
403  
						b = i>>>23;
404  
						v = b>0? 
405  
							varargsOf(stack,a+1,b-1): // exact arg count
406  
							varargsOf(stack, a+1, top-v.narg()-(a+1), v); // from prev top 
407  
						return new TailcallVarargs( stack[a], v );
408  
					}
409  
					
410  
				case Lua.OP_RETURN: /*	A B	return R(A), ... ,R(A+B-2)	(see note)	*/
411  
					b = i>>>23;
412  
					switch ( b ) {
413  
					case 0: return varargsOf(stack, a, top-v.narg()-a, v); 
414  
					case 1: return NONE;
415  
					case 2: return stack[a]; 
416  
					default:
417  
						return varargsOf(stack, a, b-1);
418  
					}
419  
					
420  
				case Lua.OP_FORLOOP: /*	A sBx	R(A)+=R(A+2): if R(A) <?= R(A+1) then { pc+=sBx: R(A+3)=R(A) }*/
421  
					{
422  
			            LuaValue limit = stack[a + 1];
423  
						LuaValue step  = stack[a + 2];
424  
						LuaValue idx   = step.add(stack[a]);
425  
			            if (step.gt_b(0)? idx.lteq_b(limit): idx.gteq_b(limit)) {
426  
		                    stack[a] = idx;
427  
		                    stack[a + 3] = idx;
428  
		                    pc += (i>>>14)-0x1ffff;
429  
			            }
430  
					}
431  
					continue;
432  
					
433  
				case Lua.OP_FORPREP: /*	A sBx	R(A)-=R(A+2): pc+=sBx				*/
434  
					{
435  
						LuaValue init  = stack[a].checknumber("'for' initial value must be a number");
436  
						LuaValue limit = stack[a + 1].checknumber("'for' limit must be a number");
437  
						LuaValue step  = stack[a + 2].checknumber("'for' step must be a number");
438  
						stack[a] = init.sub(step);
439  
						stack[a + 1] = limit;
440  
						stack[a + 2] = step;
441  
						pc += (i>>>14)-0x1ffff;
442  
					}
443  
					continue;
444  
445  
				case Lua.OP_TFORCALL: /* A C	R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));	*/
446  
					v = stack[a].invoke(varargsOf(stack[a+1],stack[a+2]));
447  
					c = (i>>14) & 0x1ff;
448  
					while (--c >= 0)
449  
						stack[a+3+c] = v.arg(c+1);
450  
					v = NONE;
451  
					continue;
452  
453  
				case Lua.OP_TFORLOOP: /* A sBx	if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx */
454  
					if (!stack[a+1].isnil()) { /* continue loop? */
455  
						stack[a] = stack[a+1];  /* save control varible. */
456  
						pc += (i>>>14)-0x1ffff;
457  
					}
458  
					continue;
459  
					
460  
				case Lua.OP_SETLIST: /*	A B C	R(A)[(C-1)*FPF+i]:= R(A+i), 1 <= i <= B	*/
461  
					{
462  
		                if ( (c=(i>>14)&0x1ff) == 0 )
463  
		                    c = code[pc++];
464  
		                int offset = (c-1) * Lua.LFIELDS_PER_FLUSH;
465  
		                o = stack[a];
466  
		                if ( (b=i>>>23) == 0 ) {
467  
		                    b = top - a - 1;
468  
		                    int m = b - v.narg(); 
469  
		                	int j=1;
470  
		                	for ( ;j<=m; j++ )
471  
		                    	o.set(offset+j, stack[a + j]);
472  
		                	for ( ;j<=b; j++ )
473  
		                    	o.set(offset+j, v.arg(j-m));
474  
		                } else {
475  
		                    o.presize( offset + b );
476  
		                    for (int j=1; j<=b; j++)
477  
		                    	o.set(offset+j, stack[a + j]);
478  
		                }
479  
					}
480  
					continue;
481  
					
482  
				case Lua.OP_CLOSURE: /*	A Bx	R(A):= closure(KPROTO[Bx])	*/
483  
					{
484  
						Prototype newp = p.p[i>>>14];
485  
						LuaClosure ncl = new LuaClosure(newp, globals);
486  
						Upvaldesc[] uv = newp.upvalues;
487  
						for ( int j=0, nup=uv.length; j<nup; ++j ) {
488  
							if (uv[j].instack)  /* upvalue refes to local variable? */
489  
								ncl.upValues[j] = findupval(stack, uv[j].idx, openups);
490  
							else  /* get upvalue from enclosing function */
491  
								ncl.upValues[j] = upValues[uv[j].idx];
492  
						}
493  
						stack[a] = ncl;
494  
					}
495  
					continue;
496  
					
497  
				case Lua.OP_VARARG: /*	A B	R(A), R(A+1), ..., R(A+B-1) = vararg		*/
498  
					b = i>>>23;
499  
					if ( b == 0 ) {
500  
						top = a + (b = varargs.narg());
501  
						v = varargs;
502  
					} else { 
503  
						for ( int j=1; j<b; ++j )
504  
							stack[a+j-1] = varargs.arg(j);
505  
					}
506  
					continue;				
507  
508  
				case Lua.OP_EXTRAARG:
509  
					throw new java.lang.IllegalArgumentException("Uexecutable opcode: OP_EXTRAARG");
510  
511  
				default:
512  
					throw new java.lang.IllegalArgumentException("Illegal opcode: " + (i & 0x3f));
513  
				}
514  
			}
515  
		} catch ( LuaError le ) {
516  
			if (le.traceback == null)
517  
				processErrorHooks(le, p, pc);
518  
			throw le;
519  
		} catch ( Exception e ) {
520  
			LuaError le = new LuaError(e);
521  
			processErrorHooks(le, p, pc);
522  
			throw le;
523  
		} finally {
524  
			if ( openups != null )
525  
				for ( int u=openups.length; --u>=0; )
526  
					if ( openups[u] != null )
527  
						openups[u].close();
528  
			if (globals != null && globals.debuglib != null)
529  
				globals.debuglib.onReturn();
530  
		}
531  
	}
532  
533  
	/**
534  
	 *  Run the error hook if there is one
535  
	 *  @param msg the message to use in error hook processing. 
536  
	 * */
537  
	String errorHook(String msg) {
538  
		if (globals == null || globals.errorfunc == null)
539  
			return msg;
540  
		LuaValue errfunc = globals.errorfunc;
541  
		globals.errorfunc = null;
542  
		try {
543  
			return errfunc.call( LuaValue.valueOf(msg) ).tojstring();
544  
		} catch ( Throwable t ) {
545  
			return "error in error handling";
546  
		} finally {
547  
			globals.errorfunc = errfunc;
548  
		}
549  
	}
550  
551  
	private void processErrorHooks(LuaError le, Prototype p, int pc) {
552  
		le.fileline = (p.source != null? p.source.tojstring(): "?") + ":" 
553  
			+ (p.lineinfo != null && pc >= 0 && pc < p.lineinfo.length? String.valueOf(p.lineinfo[pc]): "?");
554  
		le.traceback = errorHook(le.getMessage());
555  
		if (globals != null && globals.debuglib != null)
556  
			le.traceback = le.traceback + "\n" + globals.debuglib.traceback(le.level);
557  
	}
558  
	
559  
	private UpValue findupval(LuaValue[] stack, short idx, UpValue[] openups) {
560  
		final int n = openups.length;
561  
		for (int i = 0; i < n; ++i)
562  
			if (openups[i] != null && openups[i].index == idx)
563  
				return openups[i];
564  
		for (int i = 0; i < n; ++i)
565  
			if (openups[i] == null)
566  
				return openups[i] = new UpValue(stack, idx);
567  
		this.error("No space for upvalue");
568  
		return null;
569  
	}
570  
571  
	protected LuaValue getUpvalue(int i) {
572  
		return upValues[i].getValue();
573  
	}
574  
	
575  
	protected void setUpvalue(int i, LuaValue v) {
576  
		upValues[i].setValue(v);
577  
	}
578  
579  
	public String name() {
580  
		return "<"+p.shortsource()+":"+p.linedefined+">";
581  
	}
582  
583  
  public void setGlobals(Globals globals) {
584  
    this.globals = globals;
585  
  }
586  
587  
  public Globals getGlobals() {
588  
    return globals;
589  
  }
590  
}

Author comment

Current version from TinyBrain sources.

download  show line numbers   

Travelled to 12 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1000249
Snippet name: LuaClosure.java
Eternal ID of this version: #1000249/1
Text MD5: 8a1f2b3b0bacc838ddd536e86e4df7c5
Author: stefan
Category:
Type: Java source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-04-05 18:24:16
Source code size: 21488 bytes / 590 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 635 / 132
Referenced in: [show references]