All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.luaj.vm2.luajc.JavaGen Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
/*******************************************************************************
* Copyright (c) 2010 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc;

import org.luaj.vm2.Buffer;
import org.luaj.vm2.Lua;
import org.luaj.vm2.Prototype;

/**
 * TODO: 
 *   propogate constants
 *   loader can find inner classes
 */
public class JavaGen {

	public final String classname;
	public final byte[] bytecode;
	public final JavaGen[] inners;
	
	public JavaGen( Prototype p, String classname, String filename ) {
		this( new ProtoInfo(p,classname), classname, filename );
	}
	
	private JavaGen( ProtoInfo pi, String classname, String filename ) {
		this.classname = classname;
		
		// build this class
		JavaBuilder builder = new JavaBuilder(pi, classname, filename);
		scanInstructions(pi, classname, builder);
		this.bytecode = builder.completeClass();
		
		// build sub-prototypes
		if ( pi.subprotos != null ) {
			int n = pi.subprotos.length;
			inners = new JavaGen[n];
			for ( int i=0; i b+1 ) {
						builder.tobuffer();
						for ( int k=c; --k>=b; )
							builder.concatbuffer();
						builder.tovalue();
					} else {
						builder.concatvalue();
					}
					builder.storeLocal(pc, a);
					break;
					
				case Lua.OP_LOADBOOL:/*	A B C	R(A):= (Bool)B: if (C) pc++			*/
					builder.loadBoolean( b!=0 );
					builder.storeLocal( pc, a );
					if ( c!=0 ) 
						builder.addBranch(pc, JavaBuilder.BRANCH_GOTO, pc+2);
					break;
					
				case Lua.OP_JMP: /*	sBx	pc+=sBx					*/
					builder.addBranch(pc, JavaBuilder.BRANCH_GOTO, pc+1+sbx);
					break;
					
				case Lua.OP_EQ: /*	A B C	if ((RK(B) == RK(C)) ~= A) then pc++		*/
				case Lua.OP_LT: /*	A B C	if ((RK(B) <  RK(C)) ~= A) then pc++  		*/
				case Lua.OP_LE: /*	A B C	if ((RK(B) <= RK(C)) ~= A) then pc++  		*/
					loadLocalOrConstant( p, builder, pc, b );
					loadLocalOrConstant( p, builder, pc, c );
					builder.compareop(o);
					builder.addBranch(pc, (a!=0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE), pc+2);
					break;
	
				case Lua.OP_TEST: /*	A C	if not (R(A) <=> C) then pc++			*/ 
					builder.loadLocal( pc, a );
					builder.toBoolean();
					builder.addBranch(pc, (c!=0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE), pc+2);
					break;
					
				case Lua.OP_TESTSET: /*	A B C	if (R(B) <=> C) then R(A):= R(B) else pc++	*/
					builder.loadLocal( pc, b );
					builder.toBoolean();
					builder.addBranch(pc, (c!=0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE), pc+2);
					builder.loadLocal( pc, b );
					builder.storeLocal( pc, a );
					break;
					
				case Lua.OP_CALL: /*	A B C	R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */
	
					// load function
					builder.loadLocal(pc, a);
					
					// load args
					int narg = b - 1;
					switch ( narg ) {
					case 0: case 1: case 2: case 3:
						for ( int i=1; i 3
						builder.newVarargs( pc, a+1, b-1 );
						narg = -1;
						break;
					case -1: // prev vararg result
						loadVarargResults( builder, pc, a+1, vresultbase );
						narg = -1;
						break;
					}
					
					// call or invoke
					boolean useinvoke = narg<0 || c<1 || c>2;
					if ( useinvoke )
						builder.invoke(narg);
					else
						builder.call(narg);
					
					// handle results
					switch ( c ) {
					case 1: 
						builder.pop(); 
						break;
					case 2:
						if ( useinvoke ) 
							builder.arg( 1 );
						builder.storeLocal(pc, a);
						break;
					default: // fixed result count - unpack args
						for ( int i=1; i 1
						builder.newVarargs( pc, a+1, b-1 );
						break;
					case 0: // prev vararg result
						loadVarargResults( builder, pc, a+1, vresultbase );
						break;
					}
					builder.newTailcallVarargs();
					builder.areturn();
					break;
					
				case Lua.OP_RETURN: /*	A B	return R(A), ... ,R(A+B-2)	(see note)	*/
					if ( c == 1 ) {
						builder.loadNone();
					} else {
						switch ( b ) {
						case 0: loadVarargResults( builder, pc, a, vresultbase ); break;
						case 1: builder.loadNone(); break;
						case 2: builder.loadLocal(pc, a); break;
						default: builder.newVarargs(pc, a, b-1); break;
						}
					}
					builder.areturn(); 
					break;
					
				case Lua.OP_FORPREP: /*	A sBx	R(A)-=R(A+2): pc+=sBx				*/
					builder.loadLocal(pc, a);
					builder.loadLocal(pc, a+2);
					builder.binaryop( Lua.OP_SUB );
					builder.storeLocal(pc, a);
					builder.addBranch(pc, JavaBuilder.BRANCH_GOTO, pc+1+sbx);
					break;
					
				case Lua.OP_FORLOOP: /*	A sBx	R(A)+=R(A+2): if R(A) =2)
						builder.dup();
					builder.arg( 1 );
					builder.dup();
					builder.storeLocal(pc, a+2);
					builder.storeLocal(pc, a+3);
					
					// v[2]..v[c], use varargs from stack
					for ( int j=2; j<=c; j++ ) {
						if ( j 0 ) {
							builder.setlistStack( pc, a+1, index0, nstack );
							index0 += nstack;
						}
						builder.setlistVarargs( index0, vresultbase );
					} else {
						builder.setlistStack( pc, a+1, index0, b );
						builder.pop();
					}
					break;
					
				case Lua.OP_CLOSE: /*	A 	close all variables in the stack up to (>=) R(A)*/
					break;
					
				case Lua.OP_CLOSURE: /*	A Bx	R(A):= closure(KPROTO[Bx], R(A), ... ,R(A+n))	*/
				{
					Prototype newp = p.p[bx];
					String protoname = closureName(classname, bx);
					int nup = newp.nups;
					builder.closureCreate( protoname );
					if ( nup > 0 )
						builder.dup();
					builder.storeLocal( pc, a );
					if ( nup > 0 ) {
						for ( int up=0; up




© 2015 - 2024 Weber Informatics LLC | Privacy Policy