Initial draft of interpreter. Lua compiled "chunks" can be unmarshalled. Approximately half of bytecodes implemented in some form or another.
This commit is contained in:
8
.classpath
Normal file
8
.classpath
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src/main/java"/>
|
||||||
|
<classpathentry kind="src" path="src/test/java"/>
|
||||||
|
<classpathentry kind="src" path="src/test/res"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
||||||
17
.project
Normal file
17
.project
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>luaj-vm</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
13
pom.xml
Normal file
13
pom.xml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>luaj</groupId>
|
||||||
|
<artifactId>luaj</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<name>LuaJ Interpreter</name>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>LuaJ</finalName>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
33
src/main/java/lua/Builtin.java
Normal file
33
src/main/java/lua/Builtin.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package lua;
|
||||||
|
|
||||||
|
import lua.value.LFunction;
|
||||||
|
import lua.value.LString;
|
||||||
|
import lua.value.LTable;
|
||||||
|
|
||||||
|
final class Builtin extends LFunction {
|
||||||
|
|
||||||
|
static void addBuiltins(LTable table) {
|
||||||
|
table.luaSetTable( new LString( "print" ), new Builtin(0) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int PRINT = 0;
|
||||||
|
private int id;
|
||||||
|
Builtin( int id ) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform a lua call
|
||||||
|
public void luaStackCall(StackState state, int base, int nresults) {
|
||||||
|
switch ( id ) {
|
||||||
|
case PRINT:
|
||||||
|
System.out.println( String.valueOf( state.stack[base+1] ) );
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
luaUnsupportedOperation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
49
src/main/java/lua/GlobalState.java
Normal file
49
src/main/java/lua/GlobalState.java
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package lua;
|
||||||
|
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
import lua.value.LTable;
|
||||||
|
import lua.value.LValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
** `global state', shared by all threads of this state
|
||||||
|
*/
|
||||||
|
public class GlobalState {
|
||||||
|
|
||||||
|
// typedef struct global_State {
|
||||||
|
// stringtable strt; /* hash table for strings */
|
||||||
|
Hashtable strt; /* hash table for strings */
|
||||||
|
// lua_Alloc frealloc; /* function to reallocate memory */
|
||||||
|
// void *ud; /* auxiliary data to `frealloc' */
|
||||||
|
// lu_byte currentwhite;
|
||||||
|
// lu_byte gcstate; /* state of garbage collector */
|
||||||
|
// int sweepstrgc; /* position of sweep in `strt' */
|
||||||
|
// GCObject *rootgc; /* list of all collectable objects */
|
||||||
|
// GCObject **sweepgc; /* position of sweep in `rootgc' */
|
||||||
|
// GCObject *gray; /* list of gray objects */
|
||||||
|
// GCObject *grayagain; /* list of objects to be traversed atomically */
|
||||||
|
// GCObject *weak; /* list of weak tables (to be cleared) */
|
||||||
|
// GCObject *tmudata; /* last element of list of userdata to be GC */
|
||||||
|
// Mbuffer buff; /* temporary buffer for string concatentation */
|
||||||
|
StringBuffer buff; /* temporary buffer for string concatentation */
|
||||||
|
// lu_mem GCthreshold;
|
||||||
|
// lu_mem totalbytes; /* number of bytes currently allocated */
|
||||||
|
// lu_mem estimate; /* an estimate of number of bytes actually in use */
|
||||||
|
// lu_mem gcdept; /* how much GC is `behind schedule' */
|
||||||
|
// int gcpause; /* size of pause between successive GCs */
|
||||||
|
// int gcstepmul; /* GC `granularity' */
|
||||||
|
// lua_CFunction panic; /* to be called in unprotected errors */
|
||||||
|
// TValue l_registry;
|
||||||
|
// struct lua_State *mainthread;
|
||||||
|
StackState mainthread;
|
||||||
|
// UpVal uvhead; /* head of double-linked list of all open upvalues */
|
||||||
|
// struct Table *mt[NUM_TAGS]; /* metatables for basic types */
|
||||||
|
// TString *tmname[TM_N]; /* array with tag-method names */
|
||||||
|
// } global_State;
|
||||||
|
//
|
||||||
|
public static LValue getGlobalsTable() {
|
||||||
|
LTable table = new LTable();
|
||||||
|
Builtin.addBuiltins( table );
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
}
|
||||||
383
src/main/java/lua/Lua.java
Normal file
383
src/main/java/lua/Lua.java
Normal file
@@ -0,0 +1,383 @@
|
|||||||
|
package lua;
|
||||||
|
/**
|
||||||
|
* Constants for lua limits and opcodes
|
||||||
|
*
|
||||||
|
* @author jim_roseborough
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Lua {
|
||||||
|
|
||||||
|
// from llimits.h
|
||||||
|
|
||||||
|
/** maximum stack for a Lua function */
|
||||||
|
public static final int MAXSTACK = 250;
|
||||||
|
|
||||||
|
/** minimum size for the string table (must be power of 2) */
|
||||||
|
public static final int MINSTRTABSIZE = 32;
|
||||||
|
|
||||||
|
/** minimum size for string buffer */
|
||||||
|
public static final int LUA_MINBUFFER = 32;
|
||||||
|
|
||||||
|
|
||||||
|
// from lopcodes.h
|
||||||
|
|
||||||
|
/*===========================================================================
|
||||||
|
We assume that instructions are unsigned numbers.
|
||||||
|
All instructions have an opcode in the first 6 bits.
|
||||||
|
Instructions can have the following fields:
|
||||||
|
`A' : 8 bits
|
||||||
|
`B' : 9 bits
|
||||||
|
`C' : 9 bits
|
||||||
|
`Bx' : 18 bits (`B' and `C' together)
|
||||||
|
`sBx' : signed Bx
|
||||||
|
|
||||||
|
A signed argument is represented in excess K; that is, the number
|
||||||
|
value is the unsigned value minus K. K is exactly the maximum value
|
||||||
|
for that argument (so that -max is represented by 0, and +max is
|
||||||
|
represented by 2*max), which is half the maximum for the corresponding
|
||||||
|
unsigned argument.
|
||||||
|
===========================================================================*/
|
||||||
|
|
||||||
|
|
||||||
|
/* basic instruction format */
|
||||||
|
public static final int iABC = 0;
|
||||||
|
public static final int iABx = 1;
|
||||||
|
public static final int iAsBx = 2;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** size and position of opcode arguments.
|
||||||
|
*/
|
||||||
|
public static final int SIZE_C = 9;
|
||||||
|
public static final int SIZE_B = 9;
|
||||||
|
public static final int SIZE_Bx = (SIZE_C + SIZE_B);
|
||||||
|
public static final int SIZE_A = 8;
|
||||||
|
|
||||||
|
public static final int SIZE_OP = 6;
|
||||||
|
|
||||||
|
public static final int POS_OP = 0;
|
||||||
|
public static final int POS_A = (POS_OP + SIZE_OP);
|
||||||
|
public static final int POS_C = (POS_A + SIZE_A);
|
||||||
|
public static final int POS_B = (POS_C + SIZE_C);
|
||||||
|
public static final int POS_Bx = POS_C;
|
||||||
|
|
||||||
|
|
||||||
|
public static final int MAX_OP = ((1<<SIZE_OP)-1);
|
||||||
|
public static final int MAXARG_A = ((1<<SIZE_A)-1);
|
||||||
|
public static final int MAXARG_B = ((1<<SIZE_B)-1);
|
||||||
|
public static final int MAXARG_C = ((1<<SIZE_C)-1);
|
||||||
|
public static final int MAXARG_Bx = ((1<<SIZE_Bx)-1);
|
||||||
|
public static final int MAXARG_sBx = (MAXARG_Bx>>1); /* `sBx' is signed */
|
||||||
|
|
||||||
|
public static final int MASK_OP = ((1<<SIZE_OP)-1)<<POS_OP;
|
||||||
|
public static final int MASK_A = ((1<<SIZE_A)-1)<<POS_A;
|
||||||
|
public static final int MASK_B = ((1<<SIZE_B)-1)<<POS_B;
|
||||||
|
public static final int MASK_C = ((1<<SIZE_C)-1)<<POS_C;
|
||||||
|
public static final int MASK_Bx = ((1<<SIZE_Bx)-1)<<POS_Bx;
|
||||||
|
|
||||||
|
public static final int MASK_NOT_OP = ~MASK_OP;
|
||||||
|
public static final int MASK_NOT_A = ~MASK_A;
|
||||||
|
public static final int MASK_NOT_B = ~MASK_B;
|
||||||
|
public static final int MASK_NOT_C = ~MASK_C;
|
||||||
|
public static final int MASK_NOT_Bx = ~MASK_Bx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** the following macros help to manipulate instructions
|
||||||
|
*/
|
||||||
|
public static int GET_OPCODE(int i) {
|
||||||
|
return (i >> POS_OP) & MAX_OP;
|
||||||
|
}
|
||||||
|
public static int SET_OPCODE(int i,int o) {
|
||||||
|
return (i & (MASK_NOT_OP)) | ((o & MAX_OP) << POS_OP);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GETARG_A(int i) {
|
||||||
|
return (i >> POS_A) & MAXARG_A;
|
||||||
|
}
|
||||||
|
public static int SETARG_A(int i,int u) {
|
||||||
|
return (i & (MASK_NOT_A)) | ((u & MAXARG_A) << POS_A);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GETARG_B(int i) {
|
||||||
|
return (i >> POS_B) & MAXARG_B;
|
||||||
|
}
|
||||||
|
public static int SETARG_B(int i,int u) {
|
||||||
|
return (i & (MASK_NOT_B)) | ((u & MAXARG_B) << POS_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GETARG_C(int i) {
|
||||||
|
return (i >> POS_C) & MAXARG_C;
|
||||||
|
}
|
||||||
|
public static int SETARG_C(int i,int u) {
|
||||||
|
return (i & (MASK_NOT_C)) | ((u & MAXARG_C) << POS_C);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GETARG_Bx(int i) {
|
||||||
|
return (i >> POS_Bx) & MAXARG_Bx;
|
||||||
|
}
|
||||||
|
public static int SETARG_Bx(int i,int u) {
|
||||||
|
return (i & (MASK_NOT_Bx)) | ((u & MAXARG_Bx) << POS_Bx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GETARG_sBx(int i) {
|
||||||
|
return ((i >> POS_Bx) & MAXARG_Bx) - MAXARG_sBx;
|
||||||
|
}
|
||||||
|
public static int SETARG_sBx(int i,int u) {
|
||||||
|
return (i & (MASK_NOT_Bx)) | ((u + MAXARG_sBx) << POS_Bx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int CREATE_ABC(int o, int a, int b, int c) {
|
||||||
|
return (o<<POS_OP) | (a<<POS_A) | (b<<POS_B) | (c<<POS_C);
|
||||||
|
}
|
||||||
|
public static int CREATE_ABx(int o, int a, int bc) {
|
||||||
|
return (o<<POS_OP) | (a<<POS_A) | (bc<<POS_Bx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Macros to operate RK indices
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** this bit 1 means constant (0 means register) */
|
||||||
|
public static final int BITRK = (1 << (SIZE_B - 1));
|
||||||
|
|
||||||
|
/** test whether value is a constant */
|
||||||
|
public static boolean ISK(int x) {
|
||||||
|
return 0 != ((x) & BITRK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** gets the index of the constant */
|
||||||
|
public static int INDEXK(int r) {
|
||||||
|
return ((int)(r) & ~BITRK);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final int MAXINDEXRK = (BITRK - 1);
|
||||||
|
|
||||||
|
/** code a constant index as a RK value */
|
||||||
|
public static int RKASK(int x) {
|
||||||
|
return ((x) | BITRK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
** invalid register that fits in 8 bits
|
||||||
|
*/
|
||||||
|
public static final int NO_REG = MAXARG_A;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** R(x) - register
|
||||||
|
** Kst(x) - constant (in constant table)
|
||||||
|
** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** grep "ORDER OP" if you change these enums
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
name args description
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
public static final int OP_MOVE = 0;/* A B R(A) := R(B) */
|
||||||
|
public static final int OP_LOADK = 1;/* A Bx R(A) := Kst(Bx) */
|
||||||
|
public static final int OP_LOADBOOL = 2;/* A B C R(A) := (Bool)B; if (C) pc++ */
|
||||||
|
public static final int OP_LOADNIL = 3; /* A B R(A) := ... := R(B) := nil */
|
||||||
|
public static final int OP_GETUPVAL = 4; /* A B R(A) := UpValue[B] */
|
||||||
|
|
||||||
|
public static final int OP_GETGLOBAL = 5; /* A Bx R(A) := Gbl[Kst(Bx)] */
|
||||||
|
public static final int OP_GETTABLE = 6; /* A B C R(A) := R(B)[RK(C)] */
|
||||||
|
|
||||||
|
public static final int OP_SETGLOBAL = 7; /* A Bx Gbl[Kst(Bx)] := R(A) */
|
||||||
|
public static final int OP_SETUPVAL = 8; /* A B UpValue[B] := R(A) */
|
||||||
|
public static final int OP_SETTABLE = 9; /* A B C R(A)[RK(B)] := RK(C) */
|
||||||
|
|
||||||
|
public static final int OP_NEWTABLE = 10; /* A B C R(A) := {} (size = B,C) */
|
||||||
|
|
||||||
|
public static final int OP_SELF = 11; /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
|
||||||
|
|
||||||
|
public static final int OP_ADD = 12; /* A B C R(A) := RK(B) + RK(C) */
|
||||||
|
public static final int OP_SUB = 13; /* A B C R(A) := RK(B) - RK(C) */
|
||||||
|
public static final int OP_MUL = 14; /* A B C R(A) := RK(B) * RK(C) */
|
||||||
|
public static final int OP_DIV = 15; /* A B C R(A) := RK(B) / RK(C) */
|
||||||
|
public static final int OP_MOD = 16; /* A B C R(A) := RK(B) % RK(C) */
|
||||||
|
public static final int OP_POW = 17; /* A B C R(A) := RK(B) ^ RK(C) */
|
||||||
|
public static final int OP_UNM = 18; /* A B R(A) := -R(B) */
|
||||||
|
public static final int OP_NOT = 19; /* A B R(A) := not R(B) */
|
||||||
|
public static final int OP_LEN = 20; /* A B R(A) := length of R(B) */
|
||||||
|
|
||||||
|
public static final int OP_CONCAT = 21; /* A B C R(A) := R(B).. ... ..R(C) */
|
||||||
|
|
||||||
|
public static final int OP_JMP = 22; /* sBx pc+=sBx */
|
||||||
|
|
||||||
|
public static final int OP_EQ = 23; /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
|
||||||
|
public static final int OP_LT = 24; /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
|
||||||
|
public static final int OP_LE = 25; /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
|
||||||
|
|
||||||
|
public static final int OP_TEST = 26; /* A C if not (R(A) <=> C) then pc++ */
|
||||||
|
public static final int OP_TESTSET = 27; /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
|
||||||
|
|
||||||
|
public static final int OP_CALL = 28; /* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||||
|
public static final int OP_TAILCALL = 29; /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||||
|
public static final int OP_RETURN = 30; /* A B return R(A), ... ,R(A+B-2) (see note) */
|
||||||
|
|
||||||
|
public static final int OP_FORLOOP = 31; /* A sBx R(A)+=R(A+2);
|
||||||
|
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
|
||||||
|
public static final int OP_FORPREP = 32; /* A sBx R(A)-=R(A+2); pc+=sBx */
|
||||||
|
|
||||||
|
public static final int OP_TFORLOOP = 33; /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
|
||||||
|
if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */
|
||||||
|
public static final int OP_SETLIST = 34; /* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
|
||||||
|
|
||||||
|
public static final int OP_CLOSE = 35; /* A close all variables in the stack up to (>=) R(A)*/
|
||||||
|
public static final int OP_CLOSURE = 36; /* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
|
||||||
|
|
||||||
|
public static final int OP_VARARG = 37; /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
|
||||||
|
|
||||||
|
|
||||||
|
public static final int NUM_OPCODES = OP_VARARG + 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================
|
||||||
|
Notes:
|
||||||
|
(*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
|
||||||
|
and can be 0: OP_CALL then sets `top' to last_result+1, so
|
||||||
|
next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
|
||||||
|
|
||||||
|
(*) In OP_VARARG, if (B == 0) then use actual number of varargs and
|
||||||
|
set top (like in OP_CALL with C == 0).
|
||||||
|
|
||||||
|
(*) In OP_RETURN, if (B == 0) then return up to `top'
|
||||||
|
|
||||||
|
(*) In OP_SETLIST, if (B == 0) then B = `top';
|
||||||
|
if (C == 0) then next `instruction' is real C
|
||||||
|
|
||||||
|
(*) For comparisons, A specifies what condition the test should accept
|
||||||
|
(true or false).
|
||||||
|
|
||||||
|
(*) All `skips' (pc++) assume that next instruction is a jump
|
||||||
|
===========================================================================*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** masks for instruction properties. The format is:
|
||||||
|
** bits 0-1: op mode
|
||||||
|
** bits 2-3: C arg mode
|
||||||
|
** bits 4-5: B arg mode
|
||||||
|
** bit 6: instruction set register A
|
||||||
|
** bit 7: operator is a test
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static final int OpArgN = 0; /* argument is not used */
|
||||||
|
public static final int OpArgU = 1; /* argument is used */
|
||||||
|
public static final int OpArgR = 2; /* argument is a register or a jump offset */
|
||||||
|
public static final int OpArgK = 3; /* argument is a constant or register/constant */
|
||||||
|
|
||||||
|
public static final int[] luaP_opmodes = {
|
||||||
|
/* T A B C mode opcode */
|
||||||
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_MOVE */
|
||||||
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgN<<2) | (iABx), /* OP_LOADK */
|
||||||
|
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_LOADBOOL */
|
||||||
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_LOADNIL */
|
||||||
|
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_GETUPVAL */
|
||||||
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgN<<2) | (iABx), /* OP_GETGLOBAL */
|
||||||
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgK<<2) | (iABC), /* OP_GETTABLE */
|
||||||
|
(0<<7) | (0<<6) | (OpArgK<<4) | (OpArgN<<2) | (iABx), /* OP_SETGLOBAL */
|
||||||
|
(0<<7) | (0<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_SETUPVAL */
|
||||||
|
(0<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SETTABLE */
|
||||||
|
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_NEWTABLE */
|
||||||
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgK<<2) | (iABC), /* OP_SELF */
|
||||||
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_ADD */
|
||||||
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SUB */
|
||||||
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_MUL */
|
||||||
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_DIV */
|
||||||
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_MOD */
|
||||||
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_POW */
|
||||||
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_UNM */
|
||||||
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_NOT */
|
||||||
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_LEN */
|
||||||
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgR<<2) | (iABC), /* OP_CONCAT */
|
||||||
|
(0<<7) | (0<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_JMP */
|
||||||
|
(1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_EQ */
|
||||||
|
(1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_LT */
|
||||||
|
(1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_LE */
|
||||||
|
(1<<7) | (1<<6) | (OpArgR<<4) | (OpArgU<<2) | (iABC), /* OP_TEST */
|
||||||
|
(1<<7) | (1<<6) | (OpArgR<<4) | (OpArgU<<2) | (iABC), /* OP_TESTSET */
|
||||||
|
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_CALL */
|
||||||
|
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_TAILCALL */
|
||||||
|
(0<<7) | (0<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_RETURN */
|
||||||
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_FORLOOP */
|
||||||
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_FORPREP */
|
||||||
|
(1<<7) | (0<<6) | (OpArgN<<4) | (OpArgU<<2) | (iABC), /* OP_TFORLOOP */
|
||||||
|
(0<<7) | (0<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_SETLIST */
|
||||||
|
(0<<7) | (0<<6) | (OpArgN<<4) | (OpArgN<<2) | (iABC), /* OP_CLOSE */
|
||||||
|
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABx), /* OP_CLOSURE */
|
||||||
|
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_VARARG */
|
||||||
|
};
|
||||||
|
|
||||||
|
public static int getOpMode(int m) {
|
||||||
|
return luaP_opmodes[m] & 3;
|
||||||
|
}
|
||||||
|
public static int getBMode(int m) {
|
||||||
|
return (luaP_opmodes[m] >> 4) & 3;
|
||||||
|
}
|
||||||
|
public static int getCMode(int m) {
|
||||||
|
return (luaP_opmodes[m] >> 2) & 3;
|
||||||
|
}
|
||||||
|
public static boolean testAMode(int m) {
|
||||||
|
return 0 != (luaP_opmodes[m] & (1 << 6));
|
||||||
|
}
|
||||||
|
public static boolean testTMode(int m) {
|
||||||
|
return 0 != (luaP_opmodes[m] & (1 << 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** opcode names */
|
||||||
|
public static final String[] luaP_opnames = {
|
||||||
|
"MOVE",
|
||||||
|
"LOADK",
|
||||||
|
"LOADBOOL",
|
||||||
|
"LOADNIL",
|
||||||
|
"GETUPVAL",
|
||||||
|
"GETGLOBAL",
|
||||||
|
"GETTABLE",
|
||||||
|
"SETGLOBAL",
|
||||||
|
"SETUPVAL",
|
||||||
|
"SETTABLE",
|
||||||
|
"NEWTABLE",
|
||||||
|
"SELF",
|
||||||
|
"ADD",
|
||||||
|
"SUB",
|
||||||
|
"MUL",
|
||||||
|
"DIV",
|
||||||
|
"MOD",
|
||||||
|
"POW",
|
||||||
|
"UNM",
|
||||||
|
"NOT",
|
||||||
|
"LEN",
|
||||||
|
"CONCAT",
|
||||||
|
"JMP",
|
||||||
|
"EQ",
|
||||||
|
"LT",
|
||||||
|
"LE",
|
||||||
|
"TEST",
|
||||||
|
"TESTSET",
|
||||||
|
"CALL",
|
||||||
|
"TAILCALL",
|
||||||
|
"RETURN",
|
||||||
|
"FORLOOP",
|
||||||
|
"FORPREP",
|
||||||
|
"TFORLOOP",
|
||||||
|
"SETLIST",
|
||||||
|
"CLOSE",
|
||||||
|
"CLOSURE",
|
||||||
|
"VARARG",
|
||||||
|
null,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** number of list items to accumulate before a SETLIST instruction */
|
||||||
|
public static final int LFIELDS_PER_FLUSH = 50;
|
||||||
|
|
||||||
|
}
|
||||||
23
src/main/java/lua/io/Closure.java
Normal file
23
src/main/java/lua/io/Closure.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package lua.io;
|
||||||
|
|
||||||
|
import lua.StackState;
|
||||||
|
import lua.value.LValue;
|
||||||
|
|
||||||
|
public class Closure extends LValue {
|
||||||
|
public LValue env;
|
||||||
|
public Proto p;
|
||||||
|
public UpVal[] upVals;
|
||||||
|
public Closure(StackState state, Proto p) {
|
||||||
|
this.env = state.gt();
|
||||||
|
this.p = p;
|
||||||
|
upVals = new UpVal[p.nups];
|
||||||
|
for ( int i=0; i<p.nups; i++ )
|
||||||
|
upVals[i] = new UpVal();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// perform a lua call
|
||||||
|
public void luaStackCall(StackState state, int base, int nresults) {
|
||||||
|
state.vmExecute( this, base+1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
432
src/main/java/lua/io/LoadState.java
Normal file
432
src/main/java/lua/io/LoadState.java
Normal file
@@ -0,0 +1,432 @@
|
|||||||
|
package lua.io;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import lua.StackState;
|
||||||
|
import lua.value.LBoolean;
|
||||||
|
import lua.value.LDouble;
|
||||||
|
import lua.value.LInteger;
|
||||||
|
import lua.value.LNil;
|
||||||
|
import lua.value.LNumber;
|
||||||
|
import lua.value.LValue;
|
||||||
|
import lua.value.LString;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Function Prototypes
|
||||||
|
*/
|
||||||
|
public class LoadState {
|
||||||
|
|
||||||
|
/** mark for precompiled code (`<esc>Lua') */
|
||||||
|
public static final String LUA_SIGNATURE = "\033Lua";
|
||||||
|
|
||||||
|
|
||||||
|
/** for header of binary files -- this is Lua 5.1 */
|
||||||
|
public static final int LUAC_VERSION = 0x51;
|
||||||
|
|
||||||
|
/** for header of binary files -- this is the official format */
|
||||||
|
public static final int LUAC_FORMAT = 0;
|
||||||
|
|
||||||
|
/** size of header of binary files */
|
||||||
|
public static final int LUAC_HEADERSIZE = 12;
|
||||||
|
|
||||||
|
/** expected lua header bytes */
|
||||||
|
private static final int LUAC_HEADER_SIGNATURE = ('\033'<<24) | ('L'<<16) | ('u'<<8) | ('a');
|
||||||
|
|
||||||
|
// values read from the header
|
||||||
|
private int luacVersion;
|
||||||
|
private int luacFormat;
|
||||||
|
private boolean luacLittleEndian;
|
||||||
|
private int luacSizeofInt;
|
||||||
|
private int luacSizeofSizeT;
|
||||||
|
private int luacSizeofInstruction;
|
||||||
|
private int luacSizeofLuaNumber;
|
||||||
|
private boolean luacIsNumberIntegral;
|
||||||
|
|
||||||
|
/** The lua state that is loading the code */
|
||||||
|
private StackState L;
|
||||||
|
|
||||||
|
/** input stream from which we are loading */
|
||||||
|
private DataInputStream is;
|
||||||
|
|
||||||
|
/** Name of what is being loaded? */
|
||||||
|
String name;
|
||||||
|
|
||||||
|
|
||||||
|
private static final int LUA_TNONE = (-1);
|
||||||
|
|
||||||
|
private static final int LUA_TNIL = 0;
|
||||||
|
private static final int LUA_TBOOLEAN = 1;
|
||||||
|
private static final int LUA_TLIGHTUSERDATA = 2;
|
||||||
|
private static final int LUA_TNUMBER = 3;
|
||||||
|
private static final int LUA_TSTRING = 4;
|
||||||
|
private static final int LUA_TTABLE = 5;
|
||||||
|
private static final int LUA_TFUNCTION = 6;
|
||||||
|
private static final int LUA_TUSERDATA = 7;
|
||||||
|
private static final int LUA_TTHREAD = 8;
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// ** $Id$
|
||||||
|
// ** load precompiled Lua chunks
|
||||||
|
// ** See Copyright Notice in lua.h
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
// #include <string.h>
|
||||||
|
//
|
||||||
|
// #define lundump_c
|
||||||
|
// #define LUA_CORE
|
||||||
|
//
|
||||||
|
// #include "lua.h"
|
||||||
|
//
|
||||||
|
// #include "ldebug.h"
|
||||||
|
// #include "ldo.h"
|
||||||
|
// #include "lfunc.h"
|
||||||
|
// #include "lmem.h"
|
||||||
|
// #include "lobject.h"
|
||||||
|
// #include "lstring.h"
|
||||||
|
// #include "lundump.h"
|
||||||
|
// #include "lzio.h"
|
||||||
|
//
|
||||||
|
// typedef struct {
|
||||||
|
// lua_State* L;
|
||||||
|
// ZIO* Z;
|
||||||
|
// Mbuffer* b;
|
||||||
|
// const char* name;
|
||||||
|
// } LoadState;
|
||||||
|
//
|
||||||
|
// #ifdef LUAC_TRUST_BINARIES
|
||||||
|
// #define IF(c,s)
|
||||||
|
// #else
|
||||||
|
// #define IF(c,s) if (c) error(S,s)
|
||||||
|
//
|
||||||
|
// static void error(LoadState* S, const char* why)
|
||||||
|
// {
|
||||||
|
// luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why);
|
||||||
|
// luaD_throw(S->L,LUA_ERRSYNTAX);
|
||||||
|
// }
|
||||||
|
// #endif
|
||||||
|
//
|
||||||
|
// #define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
|
||||||
|
// #define LoadByte(S) (lu_byte)LoadChar(S)
|
||||||
|
// #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
|
||||||
|
// #define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
|
||||||
|
//
|
||||||
|
// static void LoadBlock(LoadState* S, void* b, size_t size)
|
||||||
|
// {
|
||||||
|
// size_t r=luaZ_read(S->Z,b,size);
|
||||||
|
// IF (r!=0, "unexpected end");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static int LoadChar(LoadState* S)
|
||||||
|
// {
|
||||||
|
// char x;
|
||||||
|
// LoadVar(S,x);
|
||||||
|
// return x;
|
||||||
|
// }
|
||||||
|
int loadByte() throws IOException {
|
||||||
|
return is.readUnsignedByte();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// static int LoadInt(LoadState* S)
|
||||||
|
// {
|
||||||
|
// int x;
|
||||||
|
// LoadVar(S,x);
|
||||||
|
// IF (x<0, "bad integer");
|
||||||
|
// return x;
|
||||||
|
// }
|
||||||
|
int loadInt() throws IOException {
|
||||||
|
if ( this.luacLittleEndian ) {
|
||||||
|
int a = is.readUnsignedByte();
|
||||||
|
int b = is.readUnsignedByte();
|
||||||
|
int c = is.readUnsignedByte();
|
||||||
|
int d = is.readUnsignedByte();
|
||||||
|
return (d << 24) | (c << 16) | (b << 8) | a;
|
||||||
|
} else {
|
||||||
|
return is.readInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long loadInt64() throws IOException {
|
||||||
|
int a,b;
|
||||||
|
if ( this.luacLittleEndian ) {
|
||||||
|
a = loadInt();
|
||||||
|
b = loadInt();
|
||||||
|
} else {
|
||||||
|
b = loadInt();
|
||||||
|
a = loadInt();
|
||||||
|
}
|
||||||
|
return (((long)b)<<32) | (((long)a)&0xffffffffL);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// static lua_Number LoadNumber(LoadState* S)
|
||||||
|
// {
|
||||||
|
// lua_Number x;
|
||||||
|
// LoadVar(S,x);
|
||||||
|
// return x;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static TString* LoadString(LoadState* S)
|
||||||
|
// {
|
||||||
|
// size_t size;
|
||||||
|
// LoadVar(S,size);
|
||||||
|
// if (size==0)
|
||||||
|
// return NULL;
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// char* s=luaZ_openspace(S->L,S->b,size);
|
||||||
|
// LoadBlock(S,s,size);
|
||||||
|
// return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
LString loadString() throws IOException {
|
||||||
|
int size = loadInt();
|
||||||
|
if ( size == 0 )
|
||||||
|
return null;
|
||||||
|
byte[] bytes = new byte[size];
|
||||||
|
is.readFully( bytes );
|
||||||
|
String s = new String( bytes, 0, size-1 );
|
||||||
|
return new LString( s );
|
||||||
|
}
|
||||||
|
|
||||||
|
LNumber loadNumber() throws IOException {
|
||||||
|
if ( this.luacIsNumberIntegral ) {
|
||||||
|
int value = loadInt();
|
||||||
|
return new LInteger( value );
|
||||||
|
} else {
|
||||||
|
long bits = loadInt64();
|
||||||
|
double value = Double.longBitsToDouble(bits);
|
||||||
|
return new LDouble( value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// static void LoadCode(LoadState* S, Proto* f)
|
||||||
|
// {
|
||||||
|
// int n=LoadInt(S);
|
||||||
|
// f->code=luaM_newvector(S->L,n,Instruction);
|
||||||
|
// f->sizecode=n;
|
||||||
|
// LoadVector(S,f->code,n,sizeof(Instruction));
|
||||||
|
// }
|
||||||
|
public void loadCode( Proto f ) throws IOException {
|
||||||
|
int n = loadInt();
|
||||||
|
int[] code = new int[n];
|
||||||
|
for ( int i=0; i<n; i++ )
|
||||||
|
code[i] = loadInt();
|
||||||
|
f.code = code;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// static Proto* LoadFunction(LoadState* S, TString* p);
|
||||||
|
//
|
||||||
|
// static void LoadConstants(LoadState* S, Proto* f)
|
||||||
|
// {
|
||||||
|
// int i,n;
|
||||||
|
// n=LoadInt(S);
|
||||||
|
// f->k=luaM_newvector(S->L,n,TValue);
|
||||||
|
// f->sizek=n;
|
||||||
|
// for (i=0; i<n; i++) setnilvalue(&f->k[i]);
|
||||||
|
// for (i=0; i<n; i++)
|
||||||
|
// {
|
||||||
|
// TValue* o=&f->k[i];
|
||||||
|
// int t=LoadChar(S);
|
||||||
|
// switch (t)
|
||||||
|
// {
|
||||||
|
// case LUA_TNIL:
|
||||||
|
// setnilvalue(o);
|
||||||
|
// break;
|
||||||
|
// case LUA_TBOOLEAN:
|
||||||
|
// setbvalue(o,LoadChar(S));
|
||||||
|
// break;
|
||||||
|
// case LUA_TNUMBER:
|
||||||
|
// setnvalue(o,LoadNumber(S));
|
||||||
|
// break;
|
||||||
|
// case LUA_TSTRING:
|
||||||
|
// setsvalue2n(S->L,o,LoadString(S));
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// IF (1, "bad constant");
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// n=LoadInt(S);
|
||||||
|
// f->p=luaM_newvector(S->L,n,Proto*);
|
||||||
|
// f->sizep=n;
|
||||||
|
// for (i=0; i<n; i++) f->p[i]=NULL;
|
||||||
|
// for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
|
||||||
|
// }
|
||||||
|
void loadConstants(Proto f) throws IOException {
|
||||||
|
int n = loadInt();
|
||||||
|
LValue[] values = new LValue[n];
|
||||||
|
for ( int i=0; i<n; i++ ) {
|
||||||
|
switch ( loadByte() ) {
|
||||||
|
case LUA_TNIL:
|
||||||
|
values[i] = LNil.NIL;
|
||||||
|
break;
|
||||||
|
case LUA_TBOOLEAN:
|
||||||
|
values[i] = (0 != loadByte()? LBoolean.TRUE: LBoolean.FALSE);
|
||||||
|
break;
|
||||||
|
case LUA_TNUMBER:
|
||||||
|
values[i] = loadNumber();
|
||||||
|
break;
|
||||||
|
case LUA_TSTRING:
|
||||||
|
values[i] = loadString();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException("bad constant");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.k = values;
|
||||||
|
|
||||||
|
n = loadInt();
|
||||||
|
Proto[] protos = new Proto[n];
|
||||||
|
for ( int i=0; i<n; i++ )
|
||||||
|
protos[i] = loadFunction(f.source);
|
||||||
|
f.p = protos;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// static void LoadDebug(LoadState* S, Proto* f)
|
||||||
|
// {
|
||||||
|
// int i,n;
|
||||||
|
// n=LoadInt(S);
|
||||||
|
// f->lineinfo=luaM_newvector(S->L,n,int);
|
||||||
|
// f->sizelineinfo=n;
|
||||||
|
// LoadVector(S,f->lineinfo,n,sizeof(int));
|
||||||
|
|
||||||
|
// n=LoadInt(S);
|
||||||
|
// f->locvars=luaM_newvector(S->L,n,LocVar);
|
||||||
|
// f->sizelocvars=n;
|
||||||
|
// for (i=0; i<n; i++) f->locvars[i].varname=NULL;
|
||||||
|
// for (i=0; i<n; i++)
|
||||||
|
// {
|
||||||
|
// f->locvars[i].varname=LoadString(S);
|
||||||
|
// f->locvars[i].startpc=LoadInt(S);
|
||||||
|
// f->locvars[i].endpc=LoadInt(S);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// n=LoadInt(S);
|
||||||
|
// f->upvalues=luaM_newvector(S->L,n,TString*);
|
||||||
|
// f->sizeupvalues=n;
|
||||||
|
// for (i=0; i<n; i++) f->upvalues[i]=NULL;
|
||||||
|
// for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
|
||||||
|
// }
|
||||||
|
void loadDebug( Proto f ) throws IOException {
|
||||||
|
int n = loadInt();
|
||||||
|
f.lineinfo = new int[n];
|
||||||
|
for ( int i=0; i<n; i++ )
|
||||||
|
f.lineinfo[i] = loadInt();
|
||||||
|
|
||||||
|
n = loadInt();
|
||||||
|
f.locvars = new LocVars[n];
|
||||||
|
for ( int i=0; i<n; i++ ) {
|
||||||
|
LString varname = loadString();
|
||||||
|
int startpc = loadInt();
|
||||||
|
int endpc = loadInt();
|
||||||
|
f.locvars[i] = new LocVars(varname, startpc, endpc);
|
||||||
|
}
|
||||||
|
|
||||||
|
n = loadInt();
|
||||||
|
f.upvalues = new LString[n];
|
||||||
|
for ( int i=0; i<n; i++ ) {
|
||||||
|
f.upvalues[i] = loadString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// static Proto* LoadFunction(LoadState* S, TString* p)
|
||||||
|
// {
|
||||||
|
// Proto* f=luaF_newproto(S->L);
|
||||||
|
// setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
|
||||||
|
// f->source=LoadString(S); if (f->source==NULL) f->source=p;
|
||||||
|
// f->linedefined=LoadInt(S);
|
||||||
|
// f->lastlinedefined=LoadInt(S);
|
||||||
|
// f->nups=LoadByte(S);
|
||||||
|
// f->numparams=LoadByte(S);
|
||||||
|
// f->is_vararg=LoadByte(S);
|
||||||
|
// f->maxstacksize=LoadByte(S);
|
||||||
|
// LoadCode(S,f);
|
||||||
|
// LoadConstants(S,f);
|
||||||
|
// LoadDebug(S,f);
|
||||||
|
// IF (!luaG_checkcode(f), "bad code");
|
||||||
|
// S->L->top--;
|
||||||
|
// return f;
|
||||||
|
// }
|
||||||
|
public Proto loadFunction(LString p) throws IOException {
|
||||||
|
Proto f = new Proto(this.L);
|
||||||
|
this.L.push(f);
|
||||||
|
f.source = loadString();
|
||||||
|
f.linedefined = loadInt();
|
||||||
|
f.lastlinedefined = loadInt();
|
||||||
|
f.nups = loadByte();
|
||||||
|
f.numparams = loadByte();
|
||||||
|
f.is_vararg = (0 != loadByte());
|
||||||
|
f.maxstacksize = loadByte();
|
||||||
|
loadCode(f);
|
||||||
|
loadConstants(f);
|
||||||
|
loadDebug(f);
|
||||||
|
|
||||||
|
// TODO: add check here, for debugging purposes, I believe
|
||||||
|
// see ldebug.c
|
||||||
|
// IF (!luaG_checkcode(f), "bad code");
|
||||||
|
|
||||||
|
this.L.pop();
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// static void LoadHeader(LoadState* S)
|
||||||
|
// {
|
||||||
|
// char h[LUAC_HEADERSIZE];
|
||||||
|
// char s[LUAC_HEADERSIZE];
|
||||||
|
// luaU_header(h);
|
||||||
|
// LoadBlock(S,s,LUAC_HEADERSIZE);
|
||||||
|
// IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
|
||||||
|
// }
|
||||||
|
public void loadHeader() throws IOException {
|
||||||
|
int sig = is.readInt();
|
||||||
|
luacVersion = is.readByte();
|
||||||
|
luacFormat = is.readByte();
|
||||||
|
luacLittleEndian = (0 != is.readByte());
|
||||||
|
luacSizeofInt = is.readByte();
|
||||||
|
luacSizeofSizeT = is.readByte();
|
||||||
|
luacSizeofInstruction = is.readByte();
|
||||||
|
luacSizeofLuaNumber = is.readByte();
|
||||||
|
luacIsNumberIntegral = (0 != is.readByte());
|
||||||
|
if ( sig != LUAC_HEADER_SIGNATURE )
|
||||||
|
throw new IllegalArgumentException("bad signature");
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// /*
|
||||||
|
// ** load precompiled chunk
|
||||||
|
// */
|
||||||
|
// Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
|
||||||
|
// {
|
||||||
|
// LoadState S;
|
||||||
|
// if (*name=='@' || *name=='=')
|
||||||
|
// S.name=name+1;
|
||||||
|
// else if (*name==LUA_SIGNATURE[0])
|
||||||
|
// S.name="binary string";
|
||||||
|
// else
|
||||||
|
// S.name=name;
|
||||||
|
// S.L=L;
|
||||||
|
// S.Z=Z;
|
||||||
|
// S.b=buff;
|
||||||
|
// LoadHeader(&S);
|
||||||
|
// return LoadFunction(&S,luaS_newliteral(L,"=?"));
|
||||||
|
// }
|
||||||
|
|
||||||
|
public static Proto undump( StackState L, InputStream stream, String name ) throws IOException {
|
||||||
|
String sname = name;
|
||||||
|
if ( name.startsWith("@") || name.startsWith("=") )
|
||||||
|
sname = name.substring(1);
|
||||||
|
else if ( name.startsWith("\033") )
|
||||||
|
sname = "binary string";
|
||||||
|
LoadState s = new LoadState( L, stream, sname );
|
||||||
|
s.loadHeader();
|
||||||
|
LString literal = new LString(L, "=?");
|
||||||
|
return s.loadFunction( literal );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Private constructor for create a load state */
|
||||||
|
private LoadState( StackState L, InputStream stream, String name ) {
|
||||||
|
this.L = L;
|
||||||
|
this.name = name;
|
||||||
|
this.is = new DataInputStream( stream );
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/main/java/lua/io/LocVars.java
Normal file
16
src/main/java/lua/io/LocVars.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package lua.io;
|
||||||
|
|
||||||
|
import lua.value.LString;
|
||||||
|
|
||||||
|
public class LocVars {
|
||||||
|
final LString m_varname;
|
||||||
|
final int m_startpc;
|
||||||
|
final int m_endpc;
|
||||||
|
|
||||||
|
public LocVars(LString varname, int startpc, int endpc) {
|
||||||
|
this.m_varname = varname;
|
||||||
|
this.m_startpc = startpc;
|
||||||
|
this.m_endpc = endpc;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
39
src/main/java/lua/io/Proto.java
Normal file
39
src/main/java/lua/io/Proto.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package lua.io;
|
||||||
|
|
||||||
|
import lua.StackState;
|
||||||
|
import lua.value.LValue;
|
||||||
|
import lua.value.LString;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Function Prototypes
|
||||||
|
*/
|
||||||
|
public class Proto extends LValue {
|
||||||
|
// TODO: what to do with state?
|
||||||
|
public Proto(StackState l) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public LValue[] k; /* constants used by the function */
|
||||||
|
// TValue *k; /* constants used by the function */
|
||||||
|
// Instruction *code;
|
||||||
|
public int[] code;
|
||||||
|
// struct Proto **p; /* functions defined inside the function */
|
||||||
|
public Proto[] p;
|
||||||
|
// int *lineinfo; /* map from opcodes to source lines */
|
||||||
|
public int[] lineinfo;
|
||||||
|
// struct LocVar *locvars; /* information about local variables */
|
||||||
|
public LocVars[] locvars;
|
||||||
|
// TString **upvalues; /* upvalue names */
|
||||||
|
public LString[] upvalues;
|
||||||
|
public LString source;
|
||||||
|
public int nups;
|
||||||
|
public int sizeupvalues;
|
||||||
|
public int sizek; /* size of `k' */
|
||||||
|
public int sizecode;
|
||||||
|
public int sizep; /* size of `p' */
|
||||||
|
public int linedefined;
|
||||||
|
public int lastlinedefined;
|
||||||
|
// GCObject *gclist;
|
||||||
|
public int numparams;
|
||||||
|
public boolean is_vararg;
|
||||||
|
public int maxstacksize;
|
||||||
|
}
|
||||||
5
src/main/java/lua/io/UpVal.java
Normal file
5
src/main/java/lua/io/UpVal.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package lua.io;
|
||||||
|
|
||||||
|
public class UpVal {
|
||||||
|
|
||||||
|
}
|
||||||
28
src/main/java/lua/value/LBoolean.java
Normal file
28
src/main/java/lua/value/LBoolean.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package lua.value;
|
||||||
|
|
||||||
|
public final class LBoolean extends LValue {
|
||||||
|
|
||||||
|
public static final LBoolean TRUE = new LBoolean("true",true);
|
||||||
|
|
||||||
|
public static final LBoolean FALSE = new LBoolean("false",false);
|
||||||
|
|
||||||
|
private final String m_name;
|
||||||
|
private final boolean m_value;
|
||||||
|
|
||||||
|
private LBoolean( String name, boolean value ) {
|
||||||
|
this.m_name = name;
|
||||||
|
this.m_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String luaAsString() {
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean luaAsBoolean() {
|
||||||
|
return m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static LBoolean valueOf(boolean value) {
|
||||||
|
return value? TRUE: FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
48
src/main/java/lua/value/LDouble.java
Normal file
48
src/main/java/lua/value/LDouble.java
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package lua.value;
|
||||||
|
|
||||||
|
import lua.Lua;
|
||||||
|
|
||||||
|
public class LDouble extends LNumber {
|
||||||
|
|
||||||
|
private final double m_value;
|
||||||
|
|
||||||
|
public LDouble(double value) {
|
||||||
|
this.m_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String luaAsString() {
|
||||||
|
return String.valueOf(m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// binary operations on integers, first dispatch
|
||||||
|
public LValue luaBinOpUnknown(int opcode, LValue lhs) {
|
||||||
|
return lhs.luaBinOpDouble( opcode, this.m_value );
|
||||||
|
}
|
||||||
|
|
||||||
|
// binary operations on mixtures of doubles and integers
|
||||||
|
public LValue luaBinOpInteger(int opcode, int rhs) {
|
||||||
|
return luaBinOpDoubleDouble( opcode, m_value, (double) rhs );
|
||||||
|
}
|
||||||
|
|
||||||
|
// binary operations on doubles
|
||||||
|
public LValue luaBinOpDouble(int opcode, double rhs) {
|
||||||
|
return luaBinOpDoubleDouble( opcode, m_value, rhs );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LValue luaBinOpDoubleDouble( int opcode, double lhs, double rhs ) {
|
||||||
|
switch ( opcode ) {
|
||||||
|
case Lua.OP_ADD: return new LDouble( lhs + rhs );
|
||||||
|
case Lua.OP_SUB: return new LDouble( lhs - rhs );
|
||||||
|
case Lua.OP_MUL: return new LDouble( lhs * rhs );
|
||||||
|
case Lua.OP_DIV: return new LDouble( lhs / rhs );
|
||||||
|
case Lua.OP_MOD: return new LDouble( lhs % rhs );
|
||||||
|
case Lua.OP_POW: return new LDouble( Math.pow(lhs, rhs) );
|
||||||
|
}
|
||||||
|
return luaUnsupportedOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int luaAsInt() {
|
||||||
|
return (int) m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
7
src/main/java/lua/value/LFunction.java
Normal file
7
src/main/java/lua/value/LFunction.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package lua.value;
|
||||||
|
|
||||||
|
public class LFunction extends LValue {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
43
src/main/java/lua/value/LInteger.java
Normal file
43
src/main/java/lua/value/LInteger.java
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package lua.value;
|
||||||
|
|
||||||
|
import lua.Lua;
|
||||||
|
|
||||||
|
public class LInteger extends LNumber {
|
||||||
|
|
||||||
|
private final int m_value;
|
||||||
|
|
||||||
|
public LInteger(int value) {
|
||||||
|
this.m_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int luaAsInt() {
|
||||||
|
return m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String luaAsString() {
|
||||||
|
return String.valueOf(m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// binary operations on integers, first dispatch
|
||||||
|
public LValue luaBinOpUnknown(int opcode, LValue lhs) {
|
||||||
|
return lhs.luaBinOpInteger( opcode, this.m_value );
|
||||||
|
}
|
||||||
|
|
||||||
|
// binary operations on integers
|
||||||
|
public LValue luaBinOpInteger(int opcode, int rhs) {
|
||||||
|
switch ( opcode ) {
|
||||||
|
case Lua.OP_ADD: return new LInteger( m_value + rhs );
|
||||||
|
case Lua.OP_SUB: return new LInteger( m_value - rhs );
|
||||||
|
case Lua.OP_MUL: return new LInteger( m_value * rhs );
|
||||||
|
case Lua.OP_DIV: return new LInteger( m_value / rhs );
|
||||||
|
case Lua.OP_MOD: return new LInteger( m_value % rhs );
|
||||||
|
case Lua.OP_POW: return new LInteger( (int) Math.pow(m_value, rhs) );
|
||||||
|
}
|
||||||
|
return luaUnsupportedOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// binary operations on mixed integer, double
|
||||||
|
public LValue luaBinOpDouble(int opcode, double rhs) {
|
||||||
|
return LDouble.luaBinOpDoubleDouble(opcode, (double) m_value, rhs );
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/main/java/lua/value/LNil.java
Normal file
13
src/main/java/lua/value/LNil.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package lua.value;
|
||||||
|
|
||||||
|
public final class LNil extends LValue {
|
||||||
|
public static final LNil NIL = new LNil();
|
||||||
|
|
||||||
|
public final String luaAsString() {
|
||||||
|
return "nil";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean luaAsBoolean() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
6
src/main/java/lua/value/LNumber.java
Normal file
6
src/main/java/lua/value/LNumber.java
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package lua.value;
|
||||||
|
|
||||||
|
abstract
|
||||||
|
public class LNumber extends LValue {
|
||||||
|
|
||||||
|
}
|
||||||
21
src/main/java/lua/value/LString.java
Normal file
21
src/main/java/lua/value/LString.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package lua.value;
|
||||||
|
|
||||||
|
import lua.StackState;
|
||||||
|
|
||||||
|
public class LString extends LValue {
|
||||||
|
|
||||||
|
final String m_string;
|
||||||
|
|
||||||
|
public LString(String string) {
|
||||||
|
this.m_string = string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: what to do with LuaState?
|
||||||
|
public LString(StackState l, String string) {
|
||||||
|
this(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String luaAsString() {
|
||||||
|
return m_string;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/main/java/lua/value/LTable.java
Normal file
29
src/main/java/lua/value/LTable.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package lua.value;
|
||||||
|
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
public class LTable extends LValue {
|
||||||
|
|
||||||
|
private Hashtable m_hash = new Hashtable();
|
||||||
|
private Vector m_array = new Vector();
|
||||||
|
|
||||||
|
public LTable() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public LTable(int narray, int nhash) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void luaSetTable(LValue key, LValue val) {
|
||||||
|
m_hash.put( key.luaAsString(), val );
|
||||||
|
m_array.add( val );
|
||||||
|
}
|
||||||
|
|
||||||
|
public LValue luaGetTable(LValue key) {
|
||||||
|
return (LValue) m_hash.get( key.luaAsString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String luaAsString() {
|
||||||
|
return m_hash.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/main/java/lua/value/LThread.java
Normal file
5
src/main/java/lua/value/LThread.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package lua.value;
|
||||||
|
|
||||||
|
public class LThread extends LValue {
|
||||||
|
|
||||||
|
}
|
||||||
65
src/main/java/lua/value/LValue.java
Normal file
65
src/main/java/lua/value/LValue.java
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package lua.value;
|
||||||
|
|
||||||
|
import lua.StackState;
|
||||||
|
|
||||||
|
abstract
|
||||||
|
public class LValue {
|
||||||
|
|
||||||
|
protected static LValue luaUnsupportedOperation() {
|
||||||
|
throw new java.lang.UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// test if value is true
|
||||||
|
public boolean luaAsBoolean() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform a lua call
|
||||||
|
public void luaStackCall(StackState state, int base, int nresults) {
|
||||||
|
luaUnsupportedOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// unsupported except for numbers
|
||||||
|
public LValue luaBinOpUnknown(int opcode, LValue lhs) {
|
||||||
|
return luaUnsupportedOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// unsupported except for numbers
|
||||||
|
public LValue luaBinOpInteger(int opcode, int m_value) {
|
||||||
|
return luaUnsupportedOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// unsupported except for numbers
|
||||||
|
public LValue luaBinOpDouble(int opcode, double m_value) {
|
||||||
|
return luaUnsupportedOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** set a value in a table
|
||||||
|
*/
|
||||||
|
public void luaSetTable(LValue key, LValue value) {
|
||||||
|
luaUnsupportedOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a value from a table */
|
||||||
|
public LValue luaGetTable(LValue value) {
|
||||||
|
return luaUnsupportedOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the value as a String
|
||||||
|
*/
|
||||||
|
public String luaAsString() {
|
||||||
|
return super.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Override standard toString with lua String conversion by default */
|
||||||
|
public String toString() {
|
||||||
|
return luaAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return value as an integer */
|
||||||
|
public int luaAsInt() {
|
||||||
|
luaUnsupportedOperation();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
49
src/test/java/LuacRunner.java
Normal file
49
src/test/java/LuacRunner.java
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import lua.StackState;
|
||||||
|
import lua.io.Closure;
|
||||||
|
import lua.io.LoadState;
|
||||||
|
import lua.io.Proto;
|
||||||
|
import lua.value.LString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Program to run a compiled lua chunk for test purposes
|
||||||
|
*
|
||||||
|
* @author jim_roseborough
|
||||||
|
*/
|
||||||
|
public class LuacRunner {
|
||||||
|
|
||||||
|
public static void main( String[] args ) throws IOException {
|
||||||
|
|
||||||
|
// get script name
|
||||||
|
String script = (args.length>0? args[0]: "src/test/res/test1.luac");
|
||||||
|
System.out.println("loading '"+script+"'");
|
||||||
|
|
||||||
|
// new lua state
|
||||||
|
StackState state = new StackState();
|
||||||
|
|
||||||
|
// push args onto stack
|
||||||
|
for ( int i=1; i<args.length; i++ )
|
||||||
|
state.push(new LString(args[i]));
|
||||||
|
|
||||||
|
// load the file
|
||||||
|
InputStream is = new FileInputStream( script );
|
||||||
|
Proto p = LoadState.undump(state, is, script);
|
||||||
|
|
||||||
|
// create closure to execute
|
||||||
|
Closure c = new Closure( state, p );
|
||||||
|
state.push( c );
|
||||||
|
for ( int i=0; i<args.length; i++ )
|
||||||
|
state.push( new LString(args[i]) );
|
||||||
|
state.docall(args.length, false);
|
||||||
|
|
||||||
|
// print result?
|
||||||
|
System.out.println("stack:");
|
||||||
|
for ( int i=0; i<state.top; i++ )
|
||||||
|
System.out.println(" ["+i+"]="+state.stack[i] );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/test/res/compile.sh
Normal file
7
src/test/res/compile.sh
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
LUA_HOME=/cygdrive/c/programs/lua5.1
|
||||||
|
for x in test1 test2 test3 test4
|
||||||
|
do
|
||||||
|
echo compiling $x
|
||||||
|
${LUA_HOME}/luac5.1.exe -l -o ${x}.luac ${x}.lua
|
||||||
|
done
|
||||||
5
src/test/res/test1.lua
Normal file
5
src/test/res/test1.lua
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
a = 123 + 456
|
||||||
|
print( a )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BIN
src/test/res/test1.luac
Normal file
BIN
src/test/res/test1.luac
Normal file
Binary file not shown.
10
src/test/res/test2.lua
Normal file
10
src/test/res/test2.lua
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
function sum(a,b,c,d) -- "sum" method
|
||||||
|
return a+b+c+d -- return sum
|
||||||
|
end
|
||||||
|
print( sum( 1, 2, 3, 4 ) )
|
||||||
|
print( sum( 5, 6, 7 ) )
|
||||||
|
print( sum( 9, 10, 11, 12, 13, 14 ) )
|
||||||
|
print( sum( sum(1,2,3,4), sum(5,6,7), sum(9,10,11,12,13,14), 15 ) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BIN
src/test/res/test2.luac
Normal file
BIN
src/test/res/test2.luac
Normal file
Binary file not shown.
6
src/test/res/test3.lua
Normal file
6
src/test/res/test3.lua
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
a = func(1, 2, 3)
|
||||||
|
a = func(3, 2, 1)
|
||||||
|
a = func(func(),func(),func())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BIN
src/test/res/test3.luac
Normal file
BIN
src/test/res/test3.luac
Normal file
Binary file not shown.
8
src/test/res/test4.lua
Normal file
8
src/test/res/test4.lua
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
function Point(x, y) -- "Point" object constructor
|
||||||
|
return { x = x, y = y } -- Creates and returns a new object (table)
|
||||||
|
end
|
||||||
|
array = { Point(10, 20), Point(30, 40), Point(50, 60) } -- Creates array of points
|
||||||
|
print(array[2].y) -- Prints 40
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BIN
src/test/res/test4.luac
Normal file
BIN
src/test/res/test4.luac
Normal file
Binary file not shown.
Reference in New Issue
Block a user