Initial sources for planned 2.0 luaj vm release. Most interpreter features and library functions working.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
org.luaj.vm2.script.LuaScriptEngineFactory
|
||||
199
src/jse/lua.java
Normal file
199
src/jse/lua.java
Normal file
@@ -0,0 +1,199 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.
|
||||
******************************************************************************/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import org.luaj.vm2.LoadState;
|
||||
import org.luaj.vm2.Lua;
|
||||
import org.luaj.vm2.LuaClosure;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.Prototype;
|
||||
import org.luaj.vm2.compiler.LuaC;
|
||||
import org.luaj.vm2.lib.DebugLib;
|
||||
import org.luaj.vm2.lib.JsePlatform;
|
||||
|
||||
|
||||
/**
|
||||
* lua command for use in java se environments.
|
||||
*/
|
||||
public class lua {
|
||||
private static final String version = Lua._VERSION + "Copyright (c) 2009 Luaj.org.org";
|
||||
|
||||
private static final String usage =
|
||||
"usage: java -cp luaj-jse.jar lua [options] [script [args]].\n" +
|
||||
"Available options are:\n" +
|
||||
" -e stat execute string 'stat'\n" +
|
||||
" -l name require library 'name'\n" +
|
||||
" -i enter interactive mode after executing 'script'\n" +
|
||||
" -v show version information\n" +
|
||||
" -- stop handling options\n" +
|
||||
" - execute stdin and stop handling options";
|
||||
|
||||
private static void usageExit() {
|
||||
System.out.println(usage);
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
private static LuaValue _G;
|
||||
|
||||
public static void main( String[] args ) throws IOException {
|
||||
|
||||
// new lua state
|
||||
LuaC.install();
|
||||
_G = JsePlatform.standardGlobals();
|
||||
DebugLib.install( _G );
|
||||
|
||||
// process args
|
||||
boolean interactive = (args.length == 0);
|
||||
boolean versioninfo = false;
|
||||
boolean processing = true;
|
||||
try {
|
||||
// stateful argument processing
|
||||
for ( int i=0; i<args.length; i++ ) {
|
||||
if ( ! processing || ! args[i].startsWith("-") ) {
|
||||
// input file - defer to last stage
|
||||
break;
|
||||
} else if ( args[i].length() <= 1 ) {
|
||||
// input file - defer to last stage
|
||||
break;
|
||||
} else {
|
||||
switch ( args[i].charAt(1) ) {
|
||||
case 'e':
|
||||
if ( ++i >= args.length )
|
||||
usageExit();
|
||||
// input script - defer to last stage
|
||||
break;
|
||||
case 'l':
|
||||
if ( ++i >= args.length )
|
||||
usageExit();
|
||||
loadLibrary( args[i] );
|
||||
break;
|
||||
case 'i':
|
||||
interactive = true;
|
||||
break;
|
||||
case 'v':
|
||||
versioninfo = true;
|
||||
break;
|
||||
case '-':
|
||||
if ( args[i].length() > 2 )
|
||||
usageExit();
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
usageExit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// echo version
|
||||
if ( versioninfo )
|
||||
System.out.println(version);
|
||||
|
||||
// input script processing
|
||||
processing = true;
|
||||
for ( int i=0; i<args.length; i++ ) {
|
||||
if ( ! processing || ! args[i].startsWith("-") ) {
|
||||
processScript( new FileInputStream(args[i]), args[i], args, i+1 );
|
||||
break;
|
||||
} else if ( args[i].length() <= 1 ) {
|
||||
processScript( System.in, "-", args, i+1 );
|
||||
break;
|
||||
} else {
|
||||
switch ( args[i].charAt(1) ) {
|
||||
case 'l':
|
||||
++i;
|
||||
break;
|
||||
case 'e':
|
||||
++i;
|
||||
processScript( new ByteArrayInputStream(args[i].getBytes()), args[i], null, 0 );
|
||||
break;
|
||||
case '-':
|
||||
processing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( interactive )
|
||||
interactiveMode();
|
||||
|
||||
} catch ( IOException ioe ) {
|
||||
System.err.println( ioe.toString() );
|
||||
System.exit(-2);
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadLibrary( String libname ) throws IOException {
|
||||
LuaValue slibname =LuaValue.valueOf(libname);
|
||||
try {
|
||||
// load via plain require
|
||||
_G.get("require").call(slibname);
|
||||
} catch ( Exception e ) {
|
||||
try {
|
||||
// load as java class
|
||||
LuaValue v = (LuaValue) Class.forName(libname).newInstance();
|
||||
v.setfenv(_G);
|
||||
v.call(slibname, _G);
|
||||
} catch ( Exception f ) {
|
||||
throw new IOException("loadLibrary("+libname+") failed: "+e+","+f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void processScript( InputStream script, String chunkname, String[] args, int offset ) throws IOException {
|
||||
try {
|
||||
LuaClosure c;
|
||||
try {
|
||||
Prototype p = LoadState.undump(script, chunkname );
|
||||
c = new LuaClosure(p,_G);
|
||||
} finally {
|
||||
script.close();
|
||||
}
|
||||
LuaValue[] a = new LuaValue[args.length-offset];
|
||||
for ( int i=0; i<a.length; i++ )
|
||||
a[i] = LuaValue.valueOf(args[offset+i]);
|
||||
c.invoke( a );
|
||||
} catch ( Throwable t ) {
|
||||
t.printStackTrace( System.err );
|
||||
}
|
||||
}
|
||||
|
||||
private static final String[] NOARGS = {};
|
||||
|
||||
private static void interactiveMode( ) throws IOException {
|
||||
BufferedReader reader = new BufferedReader( new InputStreamReader( System.in ) );
|
||||
while ( true ) {
|
||||
System.out.print("> ");
|
||||
System.out.flush();
|
||||
String line = reader.readLine();
|
||||
if ( line == null )
|
||||
return;
|
||||
processScript( new ByteArrayInputStream(line.getBytes()), "-", NOARGS, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
179
src/jse/luac.java
Normal file
179
src/jse/luac.java
Normal file
@@ -0,0 +1,179 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.
|
||||
******************************************************************************/
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.luaj.vm2.Lua;
|
||||
import org.luaj.vm2.Print;
|
||||
import org.luaj.vm2.Prototype;
|
||||
import org.luaj.vm2.compiler.DumpState;
|
||||
import org.luaj.vm2.compiler.LuaC;
|
||||
|
||||
|
||||
/**
|
||||
* Compiler for lua files to lua bytecode.
|
||||
*/
|
||||
public class luac {
|
||||
private static final String version = Lua._VERSION + "Copyright (C) 2009 luaj.org";
|
||||
|
||||
private static final String usage =
|
||||
"usage: java -cp luaj-jse.jar luac [options] [filenames].\n" +
|
||||
"Available options are:\n" +
|
||||
" - process stdin\n" +
|
||||
" -l list\n" +
|
||||
" -o name output to file 'name' (default is \"luac.out\")\n" +
|
||||
" -p parse only\n" +
|
||||
" -s strip debug information\n" +
|
||||
" -e little endian format for numbers\n" +
|
||||
" -i<n> number format 'n', (n=0,1 or 4, default="+DumpState.NUMBER_FORMAT_DEFAULT+")\n" +
|
||||
" -v show version information\n" +
|
||||
" -- stop handling options\n";
|
||||
|
||||
private static void usageExit() {
|
||||
System.out.println(usage);
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
private boolean list = false;
|
||||
private String output = "luac.out";
|
||||
private boolean parseonly = false;
|
||||
private boolean stripdebug = false;
|
||||
private boolean littleendian = false;
|
||||
private int numberformat = DumpState.NUMBER_FORMAT_DEFAULT;
|
||||
private boolean versioninfo = false;
|
||||
private boolean processing = true;
|
||||
|
||||
public static void main( String[] args ) throws IOException {
|
||||
new luac( args );
|
||||
}
|
||||
|
||||
private luac( String[] args ) throws IOException {
|
||||
|
||||
// process args
|
||||
try {
|
||||
// get stateful args
|
||||
for ( int i=0; i<args.length; i++ ) {
|
||||
if ( ! processing || ! args[i].startsWith("-") ) {
|
||||
// input file - defer to next stage
|
||||
} else if ( args[i].length() <= 1 ) {
|
||||
// input file - defer to next stage
|
||||
} else {
|
||||
switch ( args[i].charAt(1) ) {
|
||||
case 'l':
|
||||
list = true;
|
||||
break;
|
||||
case 'o':
|
||||
if ( ++i >= args.length )
|
||||
usageExit();
|
||||
output = args[i];
|
||||
break;
|
||||
case 'p':
|
||||
parseonly = true;
|
||||
break;
|
||||
case 's':
|
||||
stripdebug = true;
|
||||
break;
|
||||
case 'e':
|
||||
littleendian = true;
|
||||
break;
|
||||
case 'i':
|
||||
if ( args[i].length() <= 2 )
|
||||
usageExit();
|
||||
numberformat = Integer.parseInt(args[i].substring(2));
|
||||
break;
|
||||
case 'v':
|
||||
versioninfo = true;
|
||||
break;
|
||||
case '-':
|
||||
if ( args[i].length() > 2 )
|
||||
usageExit();
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
usageExit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// echo version
|
||||
if ( versioninfo )
|
||||
System.out.println(version);
|
||||
|
||||
// open output file
|
||||
OutputStream fos = new FileOutputStream( output );
|
||||
|
||||
// process input files
|
||||
try {
|
||||
processing = true;
|
||||
for ( int i=0; i<args.length; i++ ) {
|
||||
if ( ! processing || ! args[i].startsWith("-") ) {
|
||||
String chunkname = args[i].substring(0,args[i].length()-4);
|
||||
processScript( new FileInputStream(args[i]), chunkname, fos );
|
||||
} else if ( args[i].length() <= 1 ) {
|
||||
processScript( System.in, "stdin", fos );
|
||||
} else {
|
||||
switch ( args[i].charAt(1) ) {
|
||||
case 'o':
|
||||
++i;
|
||||
break;
|
||||
case '-':
|
||||
processing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
fos.close();
|
||||
}
|
||||
|
||||
} catch ( IOException ioe ) {
|
||||
System.err.println( ioe.toString() );
|
||||
System.exit(-2);
|
||||
}
|
||||
}
|
||||
|
||||
private void processScript( InputStream script, String chunkname, OutputStream out ) throws IOException {
|
||||
try {
|
||||
// create the chunk
|
||||
Prototype chunk = LuaC.compile(script, chunkname);
|
||||
|
||||
// list the chunk
|
||||
if (list)
|
||||
Print.printCode(chunk);
|
||||
|
||||
// write out the chunk
|
||||
if (!parseonly) {
|
||||
DumpState.dump(chunk, out, stripdebug, numberformat, littleendian);
|
||||
}
|
||||
|
||||
} catch ( Throwable t ) {
|
||||
t.printStackTrace( System.err );
|
||||
} finally {
|
||||
script.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
179
src/jse/luajc.java
Normal file
179
src/jse/luajc.java
Normal file
@@ -0,0 +1,179 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.
|
||||
******************************************************************************/
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.luaj.vm2.Lua;
|
||||
import org.luaj.vm2.compiler.DumpState;
|
||||
import org.luaj.vm2.luajc.antlr.AntlrLuaJCompiler;
|
||||
|
||||
|
||||
/**
|
||||
* Compiler for lua files to compile lua sources into java sources.
|
||||
*/
|
||||
public class luajc {
|
||||
private static final String version = Lua._VERSION + "Copyright (C) 2009 luaj.org";
|
||||
|
||||
private static final String usage =
|
||||
"usage: java -cp luaj-jse.jar,antlr-3.1.3.jar luajc [options] [filenames].\n" +
|
||||
"Available options are:\n" +
|
||||
" - process stdin\n" +
|
||||
" -l list\n" +
|
||||
" -o name output to file 'name' (default is \"luac.out\")\n" +
|
||||
" -p parse only\n" +
|
||||
" -s strip debug information\n" +
|
||||
" -e little endian format for numbers\n" +
|
||||
" -i<n> number format 'n', (n=0,1 or 4, default="+DumpState.NUMBER_FORMAT_DEFAULT+")\n" +
|
||||
" -v show version information\n" +
|
||||
" -- stop handling options\n";
|
||||
|
||||
private static void usageExit() {
|
||||
System.out.println(usage);
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
private boolean list = false;
|
||||
private String output = "luacj.out";
|
||||
private boolean parseonly = false;
|
||||
private boolean stripdebug = false;
|
||||
private boolean littleendian = false;
|
||||
private int numberformat = DumpState.NUMBER_FORMAT_DEFAULT;
|
||||
private boolean versioninfo = false;
|
||||
private boolean processing = true;
|
||||
|
||||
public static void main( String[] args ) throws IOException {
|
||||
new luajc( args );
|
||||
}
|
||||
|
||||
private luajc( String[] args ) throws IOException {
|
||||
|
||||
// process args
|
||||
try {
|
||||
// get stateful args
|
||||
for ( int i=0; i<args.length; i++ ) {
|
||||
if ( ! processing || ! args[i].startsWith("-") ) {
|
||||
// input file - defer to next stage
|
||||
} else if ( args[i].length() <= 1 ) {
|
||||
// input file - defer to next stage
|
||||
} else {
|
||||
switch ( args[i].charAt(1) ) {
|
||||
case 'l':
|
||||
list = true;
|
||||
break;
|
||||
case 'o':
|
||||
if ( ++i >= args.length )
|
||||
usageExit();
|
||||
output = args[i];
|
||||
break;
|
||||
case 'p':
|
||||
parseonly = true;
|
||||
break;
|
||||
case 's':
|
||||
stripdebug = true;
|
||||
break;
|
||||
case 'e':
|
||||
littleendian = true;
|
||||
break;
|
||||
case 'i':
|
||||
if ( args[i].length() <= 2 )
|
||||
usageExit();
|
||||
numberformat = Integer.parseInt(args[i].substring(2));
|
||||
break;
|
||||
case 'v':
|
||||
versioninfo = true;
|
||||
break;
|
||||
case '-':
|
||||
if ( args[i].length() > 2 )
|
||||
usageExit();
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
usageExit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// echo version
|
||||
if ( versioninfo )
|
||||
System.out.println(version);
|
||||
|
||||
// open output file
|
||||
OutputStream fos = new FileOutputStream( output );
|
||||
|
||||
// process input files
|
||||
try {
|
||||
processing = true;
|
||||
for ( int i=0; i<args.length; i++ ) {
|
||||
if ( ! processing || ! args[i].startsWith("-") ) {
|
||||
String chunkname = args[i].substring(0,args[i].length()-4);
|
||||
processScript( new FileInputStream(args[i]), chunkname, fos );
|
||||
} else if ( args[i].length() <= 1 ) {
|
||||
processScript( System.in, "stdin", fos );
|
||||
} else {
|
||||
switch ( args[i].charAt(1) ) {
|
||||
case 'o':
|
||||
++i;
|
||||
break;
|
||||
case '-':
|
||||
processing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
fos.close();
|
||||
}
|
||||
|
||||
} catch ( IOException ioe ) {
|
||||
System.err.println( ioe.toString() );
|
||||
System.exit(-2);
|
||||
}
|
||||
}
|
||||
|
||||
private void processScript( InputStream script, String chunkname, OutputStream out ) throws IOException {
|
||||
try {
|
||||
// create the chunk
|
||||
String source = AntlrLuaJCompiler.compile(script, chunkname);
|
||||
|
||||
// list the chunk
|
||||
if (list)
|
||||
System.out.println(source);
|
||||
|
||||
// write out the chunk
|
||||
if (!parseonly) {
|
||||
FileOutputStream fos = new FileOutputStream( chunkname+".java" );
|
||||
fos.write( source.getBytes() );
|
||||
fos.close();
|
||||
}
|
||||
|
||||
} catch ( Throwable t ) {
|
||||
t.printStackTrace( System.err );
|
||||
} finally {
|
||||
script.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
52
src/jse/org/luaj/vm2/lib/JsePlatform.java
Normal file
52
src/jse/org/luaj/vm2/lib/JsePlatform.java
Normal file
@@ -0,0 +1,52 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lib;
|
||||
|
||||
import org.luaj.vm2.LuaTable;
|
||||
import org.luaj.vm2.lib.CoroutineLib;
|
||||
import org.luaj.vm2.lib.jse.JseBaseLib;
|
||||
import org.luaj.vm2.lib.jse.JseIoLib;
|
||||
import org.luaj.vm2.lib.jse.JseMathLib;
|
||||
import org.luaj.vm2.lib.jse.JseOsLib;
|
||||
import org.luaj.vm2.lib.jse.LuajavaLib;
|
||||
|
||||
public class JsePlatform {
|
||||
|
||||
/**
|
||||
* Create a standard set of globals for JSE including all the libraries.
|
||||
*
|
||||
* @return Table of globals initialized with the standard JSE libraries
|
||||
*/
|
||||
public static LuaTable standardGlobals() {
|
||||
LuaTable _G = new JseBaseLib();
|
||||
new org.luaj.vm2.lib.PackageLib(_G);
|
||||
_G.set( "io", new org.luaj.vm2.lib.jse.JseIoLib() );
|
||||
_G.set( "math", new org.luaj.vm2.lib.jse.JseMathLib() );
|
||||
_G.set( "os", new org.luaj.vm2.lib.jse.JseOsLib() );
|
||||
_G.set( "table", new org.luaj.vm2.lib.TableLib() );
|
||||
_G.set( "string", new org.luaj.vm2.lib.StringLib() );
|
||||
_G.set( "luajava", new org.luaj.vm2.lib.jse.LuajavaLib() );
|
||||
CoroutineLib.install(_G);
|
||||
return _G;
|
||||
}
|
||||
|
||||
}
|
||||
91
src/jse/org/luaj/vm2/lib/jse/CoerceJavaToLua.java
Normal file
91
src/jse/org/luaj/vm2/lib/jse/CoerceJavaToLua.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lib.jse;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.luaj.vm2.LuaDouble;
|
||||
import org.luaj.vm2.LuaInteger;
|
||||
import org.luaj.vm2.LuaString;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
|
||||
|
||||
public class CoerceJavaToLua {
|
||||
|
||||
public static interface Coercion {
|
||||
public LuaValue coerce( Object javaValue );
|
||||
};
|
||||
|
||||
private static Map COERCIONS = new HashMap();
|
||||
|
||||
static {
|
||||
Coercion boolCoercion = new Coercion() {
|
||||
public LuaValue coerce( Object javaValue ) {
|
||||
Boolean b = (Boolean) javaValue;
|
||||
return b.booleanValue()? LuaValue.TRUE: LuaValue.FALSE;
|
||||
}
|
||||
} ;
|
||||
Coercion intCoercion = new Coercion() {
|
||||
public LuaValue coerce( Object javaValue ) {
|
||||
Number n = (Number) javaValue;
|
||||
return LuaInteger.valueOf( n.intValue() );
|
||||
}
|
||||
} ;
|
||||
Coercion charCoercion = new Coercion() {
|
||||
public LuaValue coerce( Object javaValue ) {
|
||||
Character c = (Character) javaValue;
|
||||
return LuaInteger.valueOf( c.charValue() );
|
||||
}
|
||||
} ;
|
||||
Coercion doubleCoercion = new Coercion() {
|
||||
public LuaValue coerce( Object javaValue ) {
|
||||
Number n = (Number) javaValue;
|
||||
return LuaDouble.valueOf( n.doubleValue() );
|
||||
}
|
||||
} ;
|
||||
Coercion stringCoercion = new Coercion() {
|
||||
public LuaValue coerce( Object javaValue ) {
|
||||
return LuaString.valueOf( javaValue.toString() );
|
||||
}
|
||||
} ;
|
||||
COERCIONS.put( Boolean.class, boolCoercion );
|
||||
COERCIONS.put( Byte.class, intCoercion );
|
||||
COERCIONS.put( Character.class, charCoercion );
|
||||
COERCIONS.put( Short.class, intCoercion );
|
||||
COERCIONS.put( Integer.class, intCoercion );
|
||||
COERCIONS.put( Float.class, doubleCoercion );
|
||||
COERCIONS.put( Double.class, doubleCoercion );
|
||||
COERCIONS.put( String.class, stringCoercion );
|
||||
}
|
||||
|
||||
public static LuaValue coerce(Object o) {
|
||||
if ( o == null )
|
||||
return LuaValue.NIL;
|
||||
Class clazz = o.getClass();
|
||||
Coercion c = (Coercion) COERCIONS.get( clazz );
|
||||
if ( c != null )
|
||||
return c.coerce( o );
|
||||
return LuajavaLib.toUserdata( o, clazz );
|
||||
}
|
||||
|
||||
}
|
||||
262
src/jse/org/luaj/vm2/lib/jse/CoerceLuaToJava.java
Normal file
262
src/jse/org/luaj/vm2/lib/jse/CoerceLuaToJava.java
Normal file
@@ -0,0 +1,262 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lib.jse;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.luaj.vm2.LuaValue;
|
||||
|
||||
|
||||
public class CoerceLuaToJava {
|
||||
|
||||
public static interface Coercion {
|
||||
public Object coerce( LuaValue value );
|
||||
public int score( LuaValue value );
|
||||
};
|
||||
|
||||
private static Map COERCIONS = new HashMap();
|
||||
private static Coercion OBJECT_COERCION;
|
||||
|
||||
static {
|
||||
Coercion boolCoercion = new Coercion() {
|
||||
public Object coerce(LuaValue value) {
|
||||
return value.toboolean()? Boolean.TRUE: Boolean.FALSE;
|
||||
}
|
||||
public int score(LuaValue value) {
|
||||
switch ( value.type() ) {
|
||||
case LuaValue.TNIL:
|
||||
case LuaValue.TBOOLEAN:
|
||||
return 0;
|
||||
case LuaValue.TNUMBER:
|
||||
return 1;
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
};
|
||||
Coercion byteCoercion = new Coercion() {
|
||||
public Object coerce(LuaValue value) {
|
||||
return new Byte( (byte) value.toint() );
|
||||
}
|
||||
public int score(LuaValue value) {
|
||||
switch ( value.type() ) {
|
||||
case LuaValue.TNUMBER:
|
||||
return (value.isinttype()? 1: 2);
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
};
|
||||
Coercion charCoercion = new Coercion() {
|
||||
public Object coerce(LuaValue value) {
|
||||
return new Character( (char) value.toint() );
|
||||
}
|
||||
public int score(LuaValue value) {
|
||||
switch ( value.type() ) {
|
||||
case LuaValue.TNUMBER:
|
||||
return (value.isinttype()? 1: 2);
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
};
|
||||
Coercion shortCoercion = new Coercion() {
|
||||
public Object coerce(LuaValue value) {
|
||||
return new Short( (short) value.toint() );
|
||||
}
|
||||
public int score(LuaValue value) {
|
||||
switch ( value.type() ) {
|
||||
case LuaValue.TNUMBER:
|
||||
return (value.isinttype()? 1: 2);
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
};
|
||||
Coercion intCoercion = new Coercion() {
|
||||
public Object coerce(LuaValue value) {
|
||||
return new Integer( value.toint() );
|
||||
}
|
||||
public int score(LuaValue value) {
|
||||
switch ( value.type() ) {
|
||||
case LuaValue.TNUMBER:
|
||||
return (value.isinttype()? 0: 1);
|
||||
case LuaValue.TBOOLEAN:
|
||||
case LuaValue.TNIL:
|
||||
return 2;
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
};
|
||||
Coercion longCoercion = new Coercion() {
|
||||
public Object coerce(LuaValue value) {
|
||||
return new Long( value.tolong() );
|
||||
}
|
||||
public int score(LuaValue value) {
|
||||
switch ( value.type() ) {
|
||||
case LuaValue.TNUMBER:
|
||||
return (value.isinttype()? 1: 2);
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
};
|
||||
Coercion floatCoercion = new Coercion() {
|
||||
public Object coerce(LuaValue value) {
|
||||
return new Float( value.tofloat() );
|
||||
}
|
||||
public int score( LuaValue value ) {
|
||||
switch ( value.type() ) {
|
||||
case LuaValue.TNUMBER:
|
||||
return 1;
|
||||
case LuaValue.TBOOLEAN:
|
||||
return 2;
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
};
|
||||
Coercion doubleCoercion = new Coercion() {
|
||||
public Object coerce(LuaValue value) {
|
||||
return new Double( value.todouble() );
|
||||
}
|
||||
public int score(LuaValue value) {
|
||||
switch ( value.type() ) {
|
||||
case LuaValue.TNUMBER:
|
||||
return (value.isinttype()? 1: 0);
|
||||
case LuaValue.TBOOLEAN:
|
||||
return 2;
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
};
|
||||
Coercion stringCoercion = new Coercion() {
|
||||
public Object coerce(LuaValue value) {
|
||||
return value.toString();
|
||||
}
|
||||
public int score(LuaValue value) {
|
||||
switch ( value.type() ) {
|
||||
case LuaValue.TUSERDATA:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
Coercion objectCoercion = new Coercion() {
|
||||
public Object coerce(LuaValue value) {
|
||||
switch ( value.type() ) {
|
||||
case LuaValue.TUSERDATA:
|
||||
return value.optuserdata(Object.class, null);
|
||||
case LuaValue.TSTRING:
|
||||
return value.toString();
|
||||
case LuaValue.TNUMBER:
|
||||
return (value.isinttype()?
|
||||
new Integer(value.toint()):
|
||||
new Double(value.todouble()));
|
||||
case LuaValue.TBOOLEAN:
|
||||
return value.toboolean()? Boolean.TRUE: Boolean.FALSE;
|
||||
case LuaValue.TNIL:
|
||||
return null;
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
public int score(LuaValue value) {
|
||||
switch ( value.type() ) {
|
||||
case LuaValue.TSTRING:
|
||||
return 0;
|
||||
default:
|
||||
return 0x10;
|
||||
}
|
||||
}
|
||||
};
|
||||
COERCIONS.put( Boolean.TYPE, boolCoercion );
|
||||
COERCIONS.put( Boolean.class, boolCoercion );
|
||||
COERCIONS.put( Byte.TYPE, byteCoercion );
|
||||
COERCIONS.put( Byte.class, byteCoercion );
|
||||
COERCIONS.put( Character.TYPE, charCoercion );
|
||||
COERCIONS.put( Character.class, charCoercion );
|
||||
COERCIONS.put( Short.TYPE, shortCoercion );
|
||||
COERCIONS.put( Short.class, shortCoercion );
|
||||
COERCIONS.put( Integer.TYPE, intCoercion );
|
||||
COERCIONS.put( Integer.class, intCoercion );
|
||||
COERCIONS.put( Long.TYPE, longCoercion );
|
||||
COERCIONS.put( Long.class, longCoercion );
|
||||
COERCIONS.put( Float.TYPE, floatCoercion );
|
||||
COERCIONS.put( Float.class, floatCoercion );
|
||||
COERCIONS.put( Double.TYPE, doubleCoercion );
|
||||
COERCIONS.put( Double.class, doubleCoercion );
|
||||
COERCIONS.put( String.class, stringCoercion );
|
||||
COERCIONS.put( Object.class, objectCoercion );
|
||||
}
|
||||
|
||||
static Object coerceArg(LuaValue v, Class type) {
|
||||
Coercion co = (Coercion) COERCIONS.get( type );
|
||||
if ( co != null )
|
||||
return co.coerce( v );
|
||||
Object o = v.optuserdata(type, null);
|
||||
if ( o != null )
|
||||
return o;
|
||||
return v;
|
||||
}
|
||||
|
||||
static Object[] coerceArgs(LuaValue[] suppliedArgs, Class[] parameterTypes) {
|
||||
int nargs = suppliedArgs.length;
|
||||
int n = parameterTypes.length;
|
||||
Object[] args = new Object[n];
|
||||
for ( int i=0; i<n && i<nargs; i++ )
|
||||
args[i] = coerceArg( suppliedArgs[i], parameterTypes[i] );
|
||||
return args;
|
||||
}
|
||||
|
||||
/*
|
||||
* Score parameter types for match with supplied parameter list
|
||||
*
|
||||
* 1) exact number of args
|
||||
* 2) java has more args
|
||||
* 3) java has less args
|
||||
* 4) types coerce well
|
||||
*/
|
||||
static int scoreParamTypes(LuaValue[] suppliedArgs, Class[] paramTypes) {
|
||||
int nargs = suppliedArgs.length;
|
||||
int njava = paramTypes.length;
|
||||
int score = (njava == nargs? 0: njava > nargs? 0x4000: 0x8000);
|
||||
for ( int i=0; i<nargs && i<njava; i++ ) {
|
||||
LuaValue a = suppliedArgs[i];
|
||||
Class c = paramTypes[i];
|
||||
Coercion co = (Coercion) COERCIONS.get( c );
|
||||
if ( co != null ) {
|
||||
score += co.score( a );
|
||||
} else if ( a.optuserdata(c, null) == null ) {
|
||||
score += 0x10000;
|
||||
} else {
|
||||
score += 0x100;
|
||||
}
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
}
|
||||
73
src/jse/org/luaj/vm2/lib/jse/JseBaseLib.java
Normal file
73
src/jse/org/luaj/vm2/lib/jse/JseBaseLib.java
Normal file
@@ -0,0 +1,73 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lib.jse;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
|
||||
/**
|
||||
* Base library implementation, targeted for JSE platforms.
|
||||
*
|
||||
* Implements the same library functions as org.luaj.lib.BaseLib,
|
||||
* but looks in the current directory for files loaded via
|
||||
* loadfile(), dofile() and require().
|
||||
*
|
||||
* @see org.luaj.vm2.lib.jse.JseBaseLib
|
||||
*/
|
||||
public class JseBaseLib extends org.luaj.vm2.lib.BaseLib {
|
||||
|
||||
static {
|
||||
STDIN = System.in;
|
||||
}
|
||||
|
||||
/** Construct a JSE base library instance */
|
||||
public JseBaseLib() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to open a file in the current working directory,
|
||||
* or fall back to base opener if not found.
|
||||
*
|
||||
* This implementation attempts to open the file using new File(filename).
|
||||
* It falls back to the base implementation that looks it up as a resource
|
||||
* in the class path if not found as a plain file.
|
||||
*
|
||||
* @see org.luaj.vm2.lib.BaseLib
|
||||
* @see org.luaj.vm2.lib.ResourceFinder
|
||||
*
|
||||
* @param filename
|
||||
* @return InputStream, or null if not found.
|
||||
*/
|
||||
public InputStream findResource(String filename) {
|
||||
File f = new File(filename);
|
||||
if ( ! f.exists() )
|
||||
return super.findResource(filename);
|
||||
try {
|
||||
return new FileInputStream(f);
|
||||
} catch ( IOException ioe ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
191
src/jse/org/luaj/vm2/lib/jse/JseIoLib.java
Normal file
191
src/jse/org/luaj/vm2/lib/jse/JseIoLib.java
Normal file
@@ -0,0 +1,191 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lib.jse;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
import org.luaj.vm2.LuaError;
|
||||
import org.luaj.vm2.LuaString;
|
||||
import org.luaj.vm2.lib.IoLib;
|
||||
|
||||
/**
|
||||
* Implementation of the lua io library for J2se using RandomAccessFile
|
||||
* to implement seek.
|
||||
*/
|
||||
public class JseIoLib extends IoLib {
|
||||
|
||||
public JseIoLib() {
|
||||
super();
|
||||
}
|
||||
|
||||
protected File wrapStdin() throws IOException {
|
||||
return new FileImpl(JseBaseLib.STDIN);
|
||||
}
|
||||
|
||||
protected File wrapStdout() throws IOException {
|
||||
return new FileImpl(JseBaseLib.STDOUT);
|
||||
}
|
||||
|
||||
protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
|
||||
RandomAccessFile f = new RandomAccessFile(filename,readMode? "r": "rw");
|
||||
if ( appendMode ) {
|
||||
f.seek(f.length());
|
||||
} else {
|
||||
if ( ! readMode )
|
||||
f.setLength(0);
|
||||
}
|
||||
return new FileImpl( f );
|
||||
}
|
||||
|
||||
protected File openProgram(String prog, String mode) throws IOException {
|
||||
final Process p = Runtime.getRuntime().exec(prog);
|
||||
return "w".equals(mode)?
|
||||
new FileImpl( p.getOutputStream() ):
|
||||
new FileImpl( p.getInputStream() );
|
||||
}
|
||||
|
||||
protected File tmpFile() throws IOException {
|
||||
java.io.File f = java.io.File.createTempFile(".luaj","bin");
|
||||
f.deleteOnExit();
|
||||
return new FileImpl( new RandomAccessFile(f,"rw") );
|
||||
}
|
||||
|
||||
private static void notimplemented() {
|
||||
throw new LuaError("not implemented");
|
||||
}
|
||||
|
||||
private final class FileImpl extends File {
|
||||
private final RandomAccessFile file;
|
||||
private final InputStream is;
|
||||
private final OutputStream os;
|
||||
private boolean closed = false;
|
||||
private boolean nobuffer = false;
|
||||
private FileImpl( RandomAccessFile file, InputStream is, OutputStream os ) {
|
||||
this.file = file;
|
||||
this.is = is!=null? is.markSupported()? is: new BufferedInputStream(is): null;
|
||||
this.os = os;
|
||||
}
|
||||
private FileImpl( RandomAccessFile f ) {
|
||||
this( f, null, null );
|
||||
}
|
||||
private FileImpl( InputStream i ) {
|
||||
this( null, i, null );
|
||||
}
|
||||
private FileImpl( OutputStream o ) {
|
||||
this( null, null, o );
|
||||
}
|
||||
public String toString() {
|
||||
return "file ("+this.hashCode()+")";
|
||||
}
|
||||
public boolean isstdfile() {
|
||||
return file == null;
|
||||
}
|
||||
public void close() throws IOException {
|
||||
closed = true;
|
||||
if ( file != null ) {
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
public void flush() throws IOException {
|
||||
if ( os != null )
|
||||
os.flush();
|
||||
}
|
||||
public void write(LuaString s) throws IOException {
|
||||
if ( os != null )
|
||||
os.write( s.m_bytes, s.m_offset, s.m_length );
|
||||
else if ( file != null )
|
||||
file.write( s.m_bytes, s.m_offset, s.m_length );
|
||||
else
|
||||
notimplemented();
|
||||
if ( nobuffer )
|
||||
flush();
|
||||
}
|
||||
public boolean isclosed() {
|
||||
return closed;
|
||||
}
|
||||
public int seek(String option, int pos) throws IOException {
|
||||
if ( file != null ) {
|
||||
if ( "set".equals(option) ) {
|
||||
file.seek(pos);
|
||||
} else if ( "end".equals(option) ) {
|
||||
file.seek(file.length()+pos);
|
||||
} else {
|
||||
file.seek(file.getFilePointer()+pos);
|
||||
}
|
||||
return (int) file.getFilePointer();
|
||||
}
|
||||
notimplemented();
|
||||
return 0;
|
||||
}
|
||||
public void setvbuf(String mode, int size) {
|
||||
nobuffer = "no".equals(mode);
|
||||
}
|
||||
|
||||
// get length remaining to read
|
||||
public int remaining() throws IOException {
|
||||
return file!=null? (int) (file.length()-file.getFilePointer()): -1;
|
||||
}
|
||||
|
||||
// peek ahead one character
|
||||
public int peek() throws IOException {
|
||||
if ( is != null ) {
|
||||
is.mark(1);
|
||||
int c = is.read();
|
||||
is.reset();
|
||||
return c;
|
||||
} else if ( file != null ) {
|
||||
int c = file.read();
|
||||
file.seek(file.getFilePointer()-1);
|
||||
return c;
|
||||
}
|
||||
notimplemented();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return char if read, -1 if eof, throw IOException on other exception
|
||||
public int read() throws IOException {
|
||||
if ( is != null )
|
||||
return is.read();
|
||||
else if ( file != null ) {
|
||||
return file.read();
|
||||
}
|
||||
notimplemented();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return number of bytes read if positive, -1 if eof, throws IOException
|
||||
public int read(byte[] bytes, int offset, int length) throws IOException {
|
||||
if (file!=null) {
|
||||
return file.read(bytes, offset, length);
|
||||
} else if (is!=null) {
|
||||
return is.read(bytes, offset, length);
|
||||
} else {
|
||||
notimplemented();
|
||||
}
|
||||
return length;
|
||||
}
|
||||
}
|
||||
}
|
||||
80
src/jse/org/luaj/vm2/lib/jse/JseMathLib.java
Normal file
80
src/jse/org/luaj/vm2/lib/jse/JseMathLib.java
Normal file
@@ -0,0 +1,80 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lib.jse;
|
||||
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.lib.LibFunction;
|
||||
import org.luaj.vm2.lib.OneArgFunction;
|
||||
import org.luaj.vm2.lib.TwoArgFunction;
|
||||
|
||||
/**
|
||||
* Math library implementation for use on JSE platform.
|
||||
*
|
||||
* Implements all "math" functions, including platform-specific
|
||||
* overrides for pow() and exp()
|
||||
*/
|
||||
public class JseMathLib extends org.luaj.vm2.lib.MathLib {
|
||||
|
||||
public JseMathLib() {
|
||||
LibFunction.bind( this, new J2seMathFunc1().getClass(), new String[] {
|
||||
"acos", "asin", "atan", "cosh",
|
||||
"exp", "log", "log10", "sinh",
|
||||
"tanh" } );
|
||||
LibFunction.bind( this, new J2seMathFunc2().getClass(), new String[] {
|
||||
"atan2", "pow", } );
|
||||
|
||||
}
|
||||
|
||||
public static class J2seMathFunc1 extends OneArgFunction {
|
||||
public LuaValue call(LuaValue arg) {
|
||||
switch ( opcode ) {
|
||||
case 0: return valueOf(Math.acos(arg.todouble()));
|
||||
case 1: return valueOf(Math.asin(arg.todouble()));
|
||||
case 2: return valueOf(Math.atan(arg.todouble()));
|
||||
case 3: return valueOf(Math.cosh(arg.todouble()));
|
||||
case 4: return valueOf(Math.exp(arg.todouble()));
|
||||
case 5: return valueOf(Math.log(arg.todouble()));
|
||||
case 6: return valueOf(Math.log10(arg.todouble()));
|
||||
case 7: return valueOf(Math.sinh(arg.todouble()));
|
||||
case 8: return valueOf(Math.tanh(arg.todouble()));
|
||||
}
|
||||
return NIL;
|
||||
}
|
||||
}
|
||||
|
||||
public static class J2seMathFunc2 extends TwoArgFunction {
|
||||
public LuaValue call(LuaValue arg1,LuaValue arg2) {
|
||||
switch ( opcode ) {
|
||||
case 0: return valueOf(Math.atan2(arg1.todouble(), arg2.todouble()));
|
||||
case 1: return valueOf(Math.pow(arg1.todouble(), arg2.todouble()));
|
||||
}
|
||||
return NIL;
|
||||
}
|
||||
}
|
||||
|
||||
/** Faster, better version of pow() used by arithmetic operator ^ */
|
||||
public double dpow_d(double a, double b) {
|
||||
return Math.pow(a, b);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
98
src/jse/org/luaj/vm2/lib/jse/JseOsLib.java
Normal file
98
src/jse/org/luaj/vm2/lib/jse/JseOsLib.java
Normal file
@@ -0,0 +1,98 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lib.jse;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Implementation of the lua os library for J2se.
|
||||
*
|
||||
* <p>Implements features specific to the J2se environment:
|
||||
* <bl>
|
||||
* <li>execute()</li>
|
||||
* <li>remove()</li>
|
||||
* <li>rename()</li>
|
||||
* <li>tmpname()</li>
|
||||
* </bl>
|
||||
*
|
||||
* @see org.luaj.vm2.lib.OsLib
|
||||
*/
|
||||
public class JseOsLib extends org.luaj.vm2.lib.OsLib {
|
||||
|
||||
/** return code indicating the execute() threw an I/O exception */
|
||||
public static int EXEC_IOEXCEPTION = -1;
|
||||
|
||||
/** return code indicating the execute() was interrupted */
|
||||
public static int EXEC_INTERRUPTED = -2;
|
||||
|
||||
/** return code indicating the execute() threw an unknown exception */
|
||||
public static int EXEC_ERROR = -3;
|
||||
|
||||
/** public constructor */
|
||||
public JseOsLib() {
|
||||
}
|
||||
|
||||
protected int execute(String command) {
|
||||
Runtime r = Runtime.getRuntime();
|
||||
try {
|
||||
final Process p = r.exec(command);
|
||||
try {
|
||||
p.waitFor();
|
||||
return p.exitValue();
|
||||
} finally {
|
||||
p.destroy();
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
return EXEC_IOEXCEPTION;
|
||||
} catch (InterruptedException e) {
|
||||
return EXEC_INTERRUPTED;
|
||||
} catch (Throwable t) {
|
||||
return EXEC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
protected void remove(String filename) throws IOException {
|
||||
File f = new File(filename);
|
||||
if ( ! f.exists() )
|
||||
throw new IOException("No such file or directory");
|
||||
if ( ! f.delete() )
|
||||
throw new IOException("Failed to delete");
|
||||
}
|
||||
|
||||
protected void rename(String oldname, String newname) throws IOException {
|
||||
File f = new File(oldname);
|
||||
if ( ! f.exists() )
|
||||
throw new IOException("No such file or directory");
|
||||
if ( ! f.renameTo(new File(newname)) )
|
||||
throw new IOException("Failed to delete");
|
||||
}
|
||||
|
||||
protected String tmpname() {
|
||||
try {
|
||||
java.io.File f = java.io.File.createTempFile(TMP_PREFIX ,TMP_SUFFIX);
|
||||
return f.getName();
|
||||
} catch ( IOException ioe ) {
|
||||
return super.tmpname();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
372
src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java
Normal file
372
src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java
Normal file
@@ -0,0 +1,372 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lib.jse;
|
||||
|
||||
|
||||
/** LuaJava-like bindings to Java scripting.
|
||||
*
|
||||
* TODO: coerce types on way in and out, pick method base on arg count ant types.
|
||||
*/
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.luaj.vm2.LuaError;
|
||||
import org.luaj.vm2.LuaTable;
|
||||
import org.luaj.vm2.LuaUserdata;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.Varargs;
|
||||
import org.luaj.vm2.lib.LibFunction;
|
||||
import org.luaj.vm2.lib.ThreeArgFunction;
|
||||
import org.luaj.vm2.lib.TwoArgFunction;
|
||||
import org.luaj.vm2.lib.VarArgFunction;
|
||||
|
||||
public class LuajavaLib extends LuaTable {
|
||||
|
||||
private static final int BINDCLASS = 0;
|
||||
private static final int NEWINSTANCE = 1;
|
||||
private static final int NEW = 2;
|
||||
private static final int CREATEPROXY = 3;
|
||||
private static final int LOADLIB = 4;
|
||||
|
||||
private static final String[] NAMES = {
|
||||
"bindClass",
|
||||
"newInstance",
|
||||
"new",
|
||||
"createProxy",
|
||||
"loadLib" };
|
||||
|
||||
private static final Map classMetatables = new HashMap();
|
||||
|
||||
public static void install(LuaValue globals) {
|
||||
globals.set("luajava", new LuajavaLib());
|
||||
}
|
||||
|
||||
public LuajavaLib() {
|
||||
LibFunction.bind( this, LuajavaFuncV.class, NAMES );
|
||||
}
|
||||
|
||||
// perform a lua call
|
||||
public static class LuajavaFuncV extends VarArgFunction {
|
||||
|
||||
public Varargs invoke(final Varargs args) {
|
||||
try {
|
||||
switch ( opcode ) {
|
||||
case BINDCLASS: {
|
||||
final Class clazz = Class.forName(args.checkString(1));
|
||||
return toUserdata( clazz, clazz );
|
||||
}
|
||||
case NEWINSTANCE:
|
||||
case NEW: {
|
||||
// get constructor
|
||||
final LuaValue c = args.checkvalue(1);
|
||||
final Class clazz = (opcode==NEWINSTANCE? Class.forName(c.toString()): (Class) c.checkuserdata(Class.class));
|
||||
final ParamsList params = new ParamsList( args );
|
||||
final Constructor con = resolveConstructor( clazz, params );
|
||||
|
||||
// coerce args, construct instance
|
||||
Object[] cargs = CoerceLuaToJava.coerceArgs( params.values, con.getParameterTypes() );
|
||||
Object o = con.newInstance( cargs );
|
||||
|
||||
// return result
|
||||
return toUserdata( o, clazz );
|
||||
}
|
||||
|
||||
case CREATEPROXY: {
|
||||
final int niface = args.narg()-1;
|
||||
if ( niface <= 0 )
|
||||
throw new LuaError("no interfaces");
|
||||
final LuaValue lobj = args.checktable(niface+1);
|
||||
|
||||
// get the interfaces
|
||||
final Class[] ifaces = new Class[niface];
|
||||
for ( int i=0; i<niface; i++ )
|
||||
ifaces[i] = Class.forName(args.checkString(i+1));
|
||||
|
||||
// create the invocation handler
|
||||
InvocationHandler handler = new InvocationHandler() {
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
String name = method.getName();
|
||||
LuaValue func = lobj.get(name);
|
||||
if ( func.isnil() )
|
||||
return null;
|
||||
int n = args!=null? args.length: 0;
|
||||
LuaValue[] v = new LuaValue[n];
|
||||
for ( int i=0; i<n; i++ )
|
||||
v[i] = CoerceJavaToLua.coerce(args[i]);
|
||||
LuaValue result = func.invoke(v).arg1();
|
||||
return CoerceLuaToJava.coerceArg(result, method.getReturnType());
|
||||
}
|
||||
};
|
||||
|
||||
// create the proxy object
|
||||
Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), ifaces, handler);
|
||||
|
||||
// return the proxy
|
||||
return LuaValue.userdataOf( proxy );
|
||||
}
|
||||
case LOADLIB: {
|
||||
// get constructor
|
||||
String classname = args.checkString(1);
|
||||
String methodname = args.checkString(2);
|
||||
Class clazz = Class.forName(classname);
|
||||
Method method = clazz.getMethod(methodname, new Class[] {});
|
||||
Object result = method.invoke(clazz, new Object[] {});
|
||||
if ( result instanceof LuaValue ) {
|
||||
return (LuaValue) result;
|
||||
} else {
|
||||
return NIL;
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw new LuaError("not yet supported: "+this);
|
||||
}
|
||||
} catch (LuaError e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new LuaError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ParamsList {
|
||||
public final LuaValue[] values;
|
||||
public final Class[] classes;
|
||||
public int hash;
|
||||
ParamsList( Varargs args ) {
|
||||
int n = Math.max(args.narg()-1,0);
|
||||
values = new LuaValue[n];
|
||||
classes = new Class[n];
|
||||
for ( int i=0; i<n; i++ ) {
|
||||
values[i] = args.arg(i+2);
|
||||
classes[i] = values[i].getClass();
|
||||
hash += classes[i].hashCode();
|
||||
}
|
||||
}
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
public boolean equals( Object o ) {
|
||||
return ( o instanceof ParamsList )?
|
||||
Arrays.equals( classes, ((ParamsList) o).classes ):
|
||||
false;
|
||||
}
|
||||
}
|
||||
|
||||
static LuaUserdata toUserdata(Object instance, final Class clazz) {
|
||||
LuaTable mt = (LuaTable) classMetatables.get(clazz);
|
||||
if ( mt == null ) {
|
||||
mt = new LuaTable();
|
||||
mt.set( LuaValue.INDEX, new TwoArgFunction() {
|
||||
public LuaValue call(LuaValue table, LuaValue key) {
|
||||
final String s = key.toString();
|
||||
try {
|
||||
Field f = clazz.getField(s);
|
||||
Object o = f.get(table.checkuserdata(Object.class));
|
||||
return CoerceJavaToLua.coerce( o );
|
||||
} catch (NoSuchFieldException nsfe) {
|
||||
return new LMethod(clazz,s);
|
||||
} catch (Exception e) {
|
||||
throw new LuaError(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
mt.set( LuaValue.NEWINDEX, new ThreeArgFunction() {
|
||||
public LuaValue call(LuaValue table, LuaValue key, LuaValue val) {
|
||||
String s = key.toString();
|
||||
try {
|
||||
Field f = clazz.getField(s);
|
||||
Object v = CoerceLuaToJava.coerceArg(val, f.getType());
|
||||
f.set(table.checkuserdata(Object.class),v);
|
||||
} catch (Exception e) {
|
||||
throw new LuaError(e);
|
||||
}
|
||||
return NONE;
|
||||
}
|
||||
});
|
||||
classMetatables.put(clazz, mt);
|
||||
}
|
||||
return LuaValue.userdataOf(instance,mt);
|
||||
}
|
||||
|
||||
private static final class LMethod extends VarArgFunction {
|
||||
private final Class clazz;
|
||||
private final String s;
|
||||
private LMethod(Class clazz, String s) {
|
||||
this.clazz = clazz;
|
||||
this.s = s;
|
||||
}
|
||||
public String toString() {
|
||||
return clazz.getName()+"."+s+"()";
|
||||
}
|
||||
public Varargs invoke(Varargs args) {
|
||||
try {
|
||||
// find the method
|
||||
Object instance = args.checkuserdata(1,Object.class);
|
||||
ParamsList params = new ParamsList( args );
|
||||
Method meth = resolveMethod( clazz, s, params );
|
||||
|
||||
// coerce the arguments
|
||||
Object[] margs = CoerceLuaToJava.coerceArgs( params.values, meth.getParameterTypes() );
|
||||
Object result = meth.invoke( instance, margs );
|
||||
|
||||
// coerce the result
|
||||
return CoerceJavaToLua.coerce(result);
|
||||
} catch (Exception e) {
|
||||
throw new LuaError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Map consCache =
|
||||
new HashMap();
|
||||
|
||||
private static Map consIndex =
|
||||
new HashMap();
|
||||
|
||||
private static Constructor resolveConstructor(Class clazz, ParamsList params ) {
|
||||
|
||||
// get the cache
|
||||
Map cache = (Map) consCache.get( clazz );
|
||||
if ( cache == null )
|
||||
consCache.put( clazz, cache = new HashMap() );
|
||||
|
||||
// look up in the cache
|
||||
Constructor c = (Constructor) cache.get( params );
|
||||
if ( c != null )
|
||||
return c;
|
||||
|
||||
// get index
|
||||
Map index = (Map) consIndex.get( clazz );
|
||||
if ( index == null ) {
|
||||
consIndex.put( clazz, index = new HashMap() );
|
||||
Constructor[] cons = clazz.getConstructors();
|
||||
for ( int i=0; i<cons.length; i++ ) {
|
||||
Constructor con = cons[i];
|
||||
Integer n = new Integer( con.getParameterTypes().length );
|
||||
List list = (List) index.get(n);
|
||||
if ( list == null )
|
||||
index.put( n, list = new ArrayList() );
|
||||
list.add( con );
|
||||
}
|
||||
}
|
||||
|
||||
// figure out best list of arguments == supplied args
|
||||
Integer n = new Integer( params.classes.length );
|
||||
List list = (List) index.get(n);
|
||||
if ( list == null )
|
||||
throw new IllegalArgumentException("no constructor with "+n+" args");
|
||||
|
||||
// find constructor with best score
|
||||
int bests = Integer.MAX_VALUE;
|
||||
int besti = 0;
|
||||
for ( int i=0, size=list.size(); i<size; i++ ) {
|
||||
Constructor con = (Constructor) list.get(i);
|
||||
int s = CoerceLuaToJava.scoreParamTypes(params.values, con.getParameterTypes());
|
||||
if ( s < bests ) {
|
||||
bests = s;
|
||||
besti = i;
|
||||
}
|
||||
}
|
||||
|
||||
// put into cache
|
||||
c = (Constructor) list.get(besti);
|
||||
cache.put( params, c );
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
private static Map methCache =
|
||||
new HashMap();
|
||||
|
||||
private static Map methIndex =
|
||||
new HashMap();
|
||||
|
||||
private static Method resolveMethod(Class clazz, String methodName, ParamsList params ) {
|
||||
|
||||
// get the cache
|
||||
Map nameCache = (Map) methCache.get( clazz );
|
||||
if ( nameCache == null )
|
||||
methCache.put( clazz, nameCache = new HashMap() );
|
||||
Map cache = (Map) nameCache.get( methodName );
|
||||
if ( cache == null )
|
||||
nameCache.put( methodName, cache = new HashMap() );
|
||||
|
||||
// look up in the cache
|
||||
Method m = (Method) cache.get( params );
|
||||
if ( m != null )
|
||||
return m;
|
||||
|
||||
// get index
|
||||
Map index = (Map) methIndex.get( clazz );
|
||||
if ( index == null ) {
|
||||
methIndex.put( clazz, index = new HashMap() );
|
||||
Method[] meths = clazz.getMethods();
|
||||
for ( int i=0; i<meths.length; i++ ) {
|
||||
Method meth = meths[i];
|
||||
String s = meth.getName();
|
||||
Integer n = new Integer(meth.getParameterTypes().length);
|
||||
Map map = (Map) index.get(s);
|
||||
if ( map == null )
|
||||
index.put( s, map = new HashMap() );
|
||||
List list = (List) map.get(n);
|
||||
if ( list == null )
|
||||
map.put( n, list = new ArrayList() );
|
||||
list.add( meth );
|
||||
}
|
||||
}
|
||||
|
||||
// figure out best list of arguments == supplied args
|
||||
Map map = (Map) index.get(methodName);
|
||||
if ( map == null )
|
||||
throw new IllegalArgumentException("no method named '"+methodName+"'");
|
||||
Integer n = new Integer( params.classes.length );
|
||||
List list = (List) map.get(n);
|
||||
if ( list == null )
|
||||
throw new IllegalArgumentException("no method named '"+methodName+"' with "+n+" args");
|
||||
|
||||
// find constructor with best score
|
||||
int bests = Integer.MAX_VALUE;
|
||||
int besti = 0;
|
||||
for ( int i=0, size=list.size(); i<size; i++ ) {
|
||||
Method meth = (Method) list.get(i);
|
||||
int s = CoerceLuaToJava.scoreParamTypes(params.values, meth.getParameterTypes());
|
||||
if ( s < bests ) {
|
||||
bests = s;
|
||||
besti = i;
|
||||
}
|
||||
}
|
||||
|
||||
// put into cache
|
||||
m = (Method) list.get(besti);
|
||||
cache.put( params, m );
|
||||
return m;
|
||||
}
|
||||
|
||||
}
|
||||
785
src/jse/org/luaj/vm2/luajc/JavaCodeGenerator.java
Normal file
785
src/jse/org/luaj/vm2/luajc/JavaCodeGenerator.java
Normal file
@@ -0,0 +1,785 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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 java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.luaj.vm2.lib.LibFunction;
|
||||
import org.luaj.vm2.luajc.lst.LSChunk;
|
||||
import org.luaj.vm2.luajc.lst.LSExpression;
|
||||
import org.luaj.vm2.luajc.lst.LSField;
|
||||
import org.luaj.vm2.luajc.lst.LSFunction;
|
||||
import org.luaj.vm2.luajc.lst.LSIfStatement;
|
||||
import org.luaj.vm2.luajc.lst.LSStatement;
|
||||
import org.luaj.vm2.luajc.lst.LSVariable;
|
||||
import org.luaj.vm2.luajc.lst.Name;
|
||||
import org.luaj.vm2.luajc.lst.Scope;
|
||||
import org.luaj.vm2.luajc.lst.LSExpression.BinopExpr;
|
||||
import org.luaj.vm2.luajc.lst.LSExpression.FunctionExpr;
|
||||
import org.luaj.vm2.luajc.lst.LSExpression.NumberConstant;
|
||||
import org.luaj.vm2.luajc.lst.LSExpression.StringConstant;
|
||||
import org.luaj.vm2.luajc.lst.LSExpression.TableConstructor;
|
||||
import org.luaj.vm2.luajc.lst.LSExpression.UnopExpr;
|
||||
import org.luaj.vm2.luajc.lst.LSExpression.VarargsRef;
|
||||
import org.luaj.vm2.luajc.lst.LSStatement.BreakStat;
|
||||
import org.luaj.vm2.luajc.lst.LSStatement.DoBlock;
|
||||
import org.luaj.vm2.luajc.lst.LSStatement.ForList;
|
||||
import org.luaj.vm2.luajc.lst.LSStatement.ForLoop;
|
||||
import org.luaj.vm2.luajc.lst.LSStatement.FunctionCall;
|
||||
import org.luaj.vm2.luajc.lst.LSStatement.LocalAssign;
|
||||
import org.luaj.vm2.luajc.lst.LSStatement.LocalFunction;
|
||||
import org.luaj.vm2.luajc.lst.LSStatement.RepeatUntil;
|
||||
import org.luaj.vm2.luajc.lst.LSStatement.ReturnStat;
|
||||
import org.luaj.vm2.luajc.lst.LSStatement.VarAssign;
|
||||
import org.luaj.vm2.luajc.lst.LSStatement.VarNamedFunction;
|
||||
import org.luaj.vm2.luajc.lst.LSStatement.WhileLoop;
|
||||
import org.luaj.vm2.luajc.lst.LSVariable.CallFunction;
|
||||
import org.luaj.vm2.luajc.lst.LSVariable.CallMethod;
|
||||
import org.luaj.vm2.luajc.lst.LSVariable.Field;
|
||||
import org.luaj.vm2.luajc.lst.LSVariable.Index;
|
||||
import org.luaj.vm2.luajc.lst.LSVariable.Method;
|
||||
import org.luaj.vm2.luajc.lst.LSVariable.NameReference;
|
||||
import org.luaj.vm2.luajc.lst.LSVariable.Parentheses;
|
||||
|
||||
public class JavaCodeGenerator {
|
||||
|
||||
public static String toJava(LSChunk chunk) {
|
||||
JavaCodeGenerator jcg = new JavaCodeGenerator();
|
||||
return jcg.writeChunk( chunk );
|
||||
}
|
||||
|
||||
public final Stack<StringBuffer> stringBuffers = new Stack<StringBuffer>();
|
||||
public StringBuffer sb;
|
||||
private int indent = 0;
|
||||
|
||||
public JavaCodeGenerator() {
|
||||
this.sb = new StringBuffer();
|
||||
}
|
||||
|
||||
private String writeChunk(LSChunk chunk) {
|
||||
pushFunctionContext();
|
||||
writeln( "import org.luaj.vm2.*;" );
|
||||
writeln( "import org.luaj.vm2.lib.*;" );
|
||||
writeln();
|
||||
writeln( "public class "+chunk.chunkname+" extends VarArgFunction {" );
|
||||
++indent;
|
||||
writeln( "public Varargs invoke(Varargs $args) {");
|
||||
++indent;
|
||||
writeFunctionBody( chunk.function );
|
||||
--indent;
|
||||
writeln( "}");
|
||||
--indent;
|
||||
// TODO: write out chunk constants
|
||||
writeln( "}" );
|
||||
return popFunctionContext();
|
||||
}
|
||||
|
||||
private void pushFunctionContext() {
|
||||
stringBuffers.push( sb = new StringBuffer() );
|
||||
}
|
||||
|
||||
private String popFunctionContext() {
|
||||
String v = stringBuffers.pop().toString();
|
||||
sb = stringBuffers.isEmpty()? null: stringBuffers.lastElement();
|
||||
return v;
|
||||
}
|
||||
|
||||
private void writeFunctionBody(LSFunction function) {
|
||||
if ( function.hasandlogic || function.hasorlogic )
|
||||
writeln( "LuaValue $t;" );
|
||||
if ( function.hasvarargassign )
|
||||
writeln( "Varargs $v;" );
|
||||
writeStatements( function.stats );
|
||||
if ( LSStatement.isNextStatementReachable( function.stats ) )
|
||||
writeln( "return NONE;" );
|
||||
}
|
||||
|
||||
private void writeStatements(List<LSStatement> statements) {
|
||||
for ( LSStatement s : statements ) {
|
||||
writeStatement( s );
|
||||
}
|
||||
}
|
||||
|
||||
private void writeStatement(LSStatement s) {
|
||||
if ( s==null ) return;
|
||||
switch ( s.type ) {
|
||||
case functionCall: writeFunctionCall( (LSStatement.FunctionCall) s ); break;
|
||||
case doBlock: writeDoBlock( (LSStatement.DoBlock) s ); break;
|
||||
case whileLoop: writeWhileLoop( (LSStatement.WhileLoop) s ); break;
|
||||
case repeatUntil: writeRepeatUntil( (LSStatement.RepeatUntil) s ); break;
|
||||
case varAssign: writeVarAssign( (LSStatement.VarAssign) s ); break;
|
||||
case forLoop: writeForLoop( (LSStatement.ForLoop) s ); break;
|
||||
case forList: writeForList( (LSStatement.ForList) s ); break;
|
||||
case varNamedFunction: writeVarNamedFunction((LSStatement.VarNamedFunction) s ); break;
|
||||
case localFunction: writeLocalFunction( (LSStatement.LocalFunction) s ); break;
|
||||
case localAssign: writeLocalAssign( (LSStatement.LocalAssign) s ); break;
|
||||
case returnStat: writeReturnStat( (LSStatement.ReturnStat) s ); break;
|
||||
case breakStat: writeBreakStat( (LSStatement.BreakStat) s ); break;
|
||||
case ifStat: writeIfStat( (LSIfStatement) s ); break;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeFunctionCall(FunctionCall s) {
|
||||
writeindent();
|
||||
write( eval(s.variable)+";" );
|
||||
writeln();
|
||||
}
|
||||
|
||||
private void writeDoBlock(DoBlock s) {
|
||||
writeln( "{" );
|
||||
++indent;
|
||||
writeStatements( s.statements );
|
||||
--indent;
|
||||
writeln( "}" );
|
||||
}
|
||||
|
||||
private void writeWhileLoop(WhileLoop s) {
|
||||
writeln( "while ("+eval(s.condition)+".toboolean()) {" );
|
||||
++indent;
|
||||
writeStatements( s.statements );
|
||||
--indent;
|
||||
writeln( "}" );
|
||||
}
|
||||
|
||||
private void writeRepeatUntil(RepeatUntil s) {
|
||||
writeln( "do {" );
|
||||
++indent;
|
||||
writeStatements( s.statements );
|
||||
--indent;
|
||||
writeln( "} while (!"+eval(s.condition)+");" );
|
||||
}
|
||||
|
||||
private void writeForLoop(ForLoop s) {
|
||||
writeln( "{" );
|
||||
++indent;
|
||||
// TODO: name handling, also upvalues!
|
||||
String index = javaName( s.index );
|
||||
String limit = javaName( s.scope.declare("$limit") );
|
||||
String step = javaName( s.scope.declare("$step") );
|
||||
writeln( "LuaValue "+index+"="+eval(s.initial)+";" );
|
||||
writeln( "final LuaValue "+limit+"="+eval(s.limit)+";" );
|
||||
if ( s.step != null ) {
|
||||
writeln( "final LuaValue "+step+"="+eval(s.step)+";" );
|
||||
writeln( "final boolean "+step+"$b="+step+".gt_b(0);" );
|
||||
}
|
||||
if ( s.step != null ) {
|
||||
writeln( "for ( ; "+index+".testfor_b("+limit+","+step+"$b); "+index+"="+index+".add("+step+") ) {" );
|
||||
} else {
|
||||
writeln( "for ( ; "+index+".lteq_b("+limit+"); "+index+"="+index+".add(1) ) {" );
|
||||
}
|
||||
++indent;
|
||||
writeStatements( s.statements );
|
||||
--indent;
|
||||
writeln( "}" );
|
||||
--indent;
|
||||
writeln( "}" );
|
||||
}
|
||||
|
||||
private void writeForList(ForList s) {
|
||||
writeln( "{" );
|
||||
++indent;
|
||||
List<String> exprs = evalExpressions(s.expressions, 3, s.scope);
|
||||
// TODO: upvalues handling!
|
||||
String fun = javaName( s.scope.declare("$f") );
|
||||
String sta = javaName( s.scope.declare("$s") );
|
||||
String var = javaName( s.scope.declare("$var") );
|
||||
String res = javaName( s.scope.declare("$res") );
|
||||
writeln( "LuaValue "+fun+"="+exprs.get(0)+";" );
|
||||
writeln( "LuaValue "+sta+"="+exprs.get(1)+";" );
|
||||
writeln( "LuaValue "+var+"="+exprs.get(2)+";" );
|
||||
writeln( "while ( true ) {" );
|
||||
++indent;
|
||||
writeln( "Varargs "+res+" = "+fun+".invoke(varargsOf("+sta+","+var+"));" );
|
||||
for ( int i=1, n=s.names.size(); i<=n; i++ )
|
||||
writeln( "LuaValue "+javaName(s.names.get(i-1))+"="+res+".arg("+i+");" );
|
||||
writeln( var+"="+javaName(s.names.get(0))+";" );
|
||||
writeln( "if ( "+var+".isnil() ) break;" );
|
||||
writeStatements( s.statements );
|
||||
--indent;
|
||||
writeln( "}" );
|
||||
--indent;
|
||||
writeln( "}" );
|
||||
}
|
||||
|
||||
private final static Set<String> reserved = new HashSet<String>();
|
||||
static {
|
||||
String[] specials = {
|
||||
// keywors used by our code generator
|
||||
"name", "opcode", "env",
|
||||
|
||||
// java keywords
|
||||
"abstract", "continue", "for", "new", "switch",
|
||||
"assert", "default", "goto", "package", "synchronized",
|
||||
"boolean", "do", "if", "private", "this",
|
||||
"break", "double", "implements", "protected", "throw",
|
||||
"byte", "else", "import", "public", "throws",
|
||||
"case", "enum", "instanceof", "return", "transient",
|
||||
"catch", "extends", "int", "short", "try",
|
||||
"char", "final", "interface", "static", "void",
|
||||
"class", "finally", "long", "strictfp", "volatile",
|
||||
"const", "float", "native", "super", "while",
|
||||
};
|
||||
for ( int i=0; i<specials.length; i++ )
|
||||
reserved.add( specials[i] );
|
||||
java.lang.reflect.Field[] f = LibFunction.class.getFields();
|
||||
for ( int i=0; i<f.length; i++ )
|
||||
reserved.add( f[i].getName() );
|
||||
}
|
||||
|
||||
private String javaName(Name name) {
|
||||
return name.innerrevision>0?
|
||||
name.luaname+"$"+name.innerrevision:
|
||||
reserved.contains(name.luaname)? (name.luaname+"$"): name.luaname;
|
||||
}
|
||||
|
||||
private void writeVarNamedFunction(VarNamedFunction s) {
|
||||
String funcdef = evalFuncbody(s.funcbody);
|
||||
writeAssign( s.funcname, funcdef );
|
||||
}
|
||||
|
||||
private String evalFuncbody(LSFunction funcbody) {
|
||||
pushFunctionContext();
|
||||
int n = funcbody.paramnames!=null? funcbody.paramnames.size(): 0;
|
||||
boolean isvararg = (funcbody.isvararg || n > 3);
|
||||
if ( isvararg ) {
|
||||
write( "new VarArgFunction(env) {\n" );
|
||||
++indent;
|
||||
writeln( "public Varargs invoke(Varargs $args) {" );
|
||||
++indent;
|
||||
for ( int i=0; i<n; i++ ) {
|
||||
Name name = funcbody.paramnames.get(i);
|
||||
if ( name.isupvalue )
|
||||
writeln( "final LuaValue[] "+javaName(funcbody.paramnames.get(i))+"={$args.arg("+(i+1)+")};" );
|
||||
else
|
||||
writeln( "LuaValue "+javaName(funcbody.paramnames.get(i))+"=$args.arg("+(i+1)+");" );
|
||||
}
|
||||
if ( (n > 0 && funcbody.usesvarargs) || funcbody.needsarg )
|
||||
writeln( "$args = $args.subargs("+(n+1)+");" );
|
||||
if ( funcbody.needsarg )
|
||||
writeln( "LuaValue arg = new LuaTable($args);" );
|
||||
else if ( funcbody.hasarg )
|
||||
writeln( "LuaValue arg = NIL;" );
|
||||
writeFunctionBody(funcbody);
|
||||
--indent;
|
||||
writeln( "}" );
|
||||
--indent;
|
||||
writeindent();
|
||||
write( "}" );
|
||||
} else {
|
||||
write(
|
||||
n==0? "new ZeroArgFunction(env) {\n":
|
||||
n==1? "new OneArgFunction(env) {\n":
|
||||
n==2? "new TwoArgFunction(env) {\n":
|
||||
"new ThreeArgFunction(env) {\n" );
|
||||
++indent;
|
||||
writeindent();
|
||||
write( "public LuaValue call(");
|
||||
for ( int i=0; i<n; i++ ) {
|
||||
if (i>0) write( "," );
|
||||
Name name = funcbody.paramnames.get(i);
|
||||
if ( name.isupvalue )
|
||||
write( "LuaValue "+javaName(name)+"$u" );
|
||||
else
|
||||
write( "LuaValue "+javaName(name) );
|
||||
}
|
||||
write( ") {" );
|
||||
writeln();
|
||||
++indent;
|
||||
|
||||
// upvalues
|
||||
for ( int i=0; i<n; i++ ) {
|
||||
Name name = funcbody.paramnames.get(i);
|
||||
if ( name.isupvalue )
|
||||
writeln( "final LuaValue[] "+javaName(name)+"={"+javaName(name)+"$u};" );
|
||||
}
|
||||
|
||||
// function body
|
||||
writeFunctionBody(funcbody);
|
||||
--indent;
|
||||
writeln( "}" );
|
||||
--indent;
|
||||
writeindent();
|
||||
write( "}" );
|
||||
}
|
||||
return popFunctionContext();
|
||||
}
|
||||
|
||||
private void writeVarAssign(VarAssign s) {
|
||||
int nassign = s.variables.size();
|
||||
List<String> exprs = evalExpressions(s.expressions, nassign, s.scope);
|
||||
for ( int i=0; i<nassign; i++ )
|
||||
writeAssign( s.variables.get(i), exprs.get(i) );
|
||||
for ( int i=nassign; i<exprs.size(); i++ )
|
||||
writeln( exprs.get(i) );
|
||||
}
|
||||
|
||||
private void writeLocalFunction(LocalFunction s) {
|
||||
String funcdef = evalFuncbody(s.funcbody);
|
||||
if ( s.name.isupvalue ) {
|
||||
writeln( "final LuaValue[] "+javaName(s.name)+"={null};" );
|
||||
writeln( javaName(s.name)+"[0]="+funcdef+";" );
|
||||
} else
|
||||
writeln( "LuaValue "+javaName(s.name)+"="+funcdef+";" );
|
||||
}
|
||||
|
||||
private void writeLocalAssign(LocalAssign s) {
|
||||
int nassign = s.names.size();
|
||||
List<String> exprs = evalExpressions(s.expressions, nassign, s.scope);
|
||||
for ( int i=0; i<nassign; i++ ) {
|
||||
Name name= s.names.get(i);
|
||||
if ( name.isupvalue )
|
||||
writeln( "final LuaValue[] "+javaName(name)+"={"+exprs.get(i)+"};" );
|
||||
else
|
||||
writeln( "LuaValue "+javaName(name)+"="+exprs.get(i)+";" );
|
||||
}
|
||||
for ( int i=nassign; i<exprs.size(); i++ )
|
||||
writeln( exprs.get(i)+";" );
|
||||
}
|
||||
|
||||
/** Evaluate expressions for use in assignment
|
||||
* @param scope */
|
||||
private List<String> evalExpressions(List<LSExpression> exprs, int nassign, Scope scope) {
|
||||
int nexpr = (exprs!=null? exprs.size(): 0);
|
||||
List<String> e = new ArrayList<String>(nexpr);
|
||||
boolean hasvarargs = false;
|
||||
for ( int i=0; i<nexpr || i<nassign; i++ ) {
|
||||
if ( i<nexpr-1 || nassign <= nexpr ) {
|
||||
e.add( eval( exprs.get(i) ) );
|
||||
} else if ( i==nexpr-1 ) {
|
||||
int nr = exprs.get(i).getNumReturns();
|
||||
hasvarargs = (nr==-1) || (nr>1);
|
||||
if ( hasvarargs )
|
||||
e.add( "($v="+eval(exprs.get(i))+").arg1()" );
|
||||
else
|
||||
e.add( eval(exprs.get(i)) );
|
||||
} else if (hasvarargs) {
|
||||
e.add( "$v.arg("+(i-nexpr+2)+")" );
|
||||
} else {
|
||||
e.add( "NIL" );
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
private void writeReturnStat(ReturnStat s) {
|
||||
int n = s.expressions!=null? s.expressions.size(): 0;
|
||||
if ( ! s.function.isvararg )
|
||||
writeln( n==0? "return NONE;": "return "+eval(s.expressions.get(0))+";" );
|
||||
else {
|
||||
writeindent();
|
||||
switch ( n ) {
|
||||
case 0:
|
||||
write( "return NONE;" );
|
||||
break;
|
||||
case 1:
|
||||
write( "return "+eval( s.expressions.get(0))+";" );
|
||||
break;
|
||||
case 2: case 3: {
|
||||
write( "return varargsOf(" );
|
||||
for ( int i=0; i<n; i++ ) {
|
||||
if (i>0) write( "," );
|
||||
write( eval( s.expressions.get(i)) );
|
||||
}
|
||||
write( ");" );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
write( "return varargsOf(new LuaValue[] {" );
|
||||
for ( int i=0; i<n-1; i++ ) {
|
||||
if (i>0) write( "," );
|
||||
write( eval( s.expressions.get(i)) );
|
||||
}
|
||||
write( "},"+eval(s.expressions.get(n-1))+");" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
writeln();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBreakStat(BreakStat s) {
|
||||
writeln( "break;" );
|
||||
}
|
||||
|
||||
private void writeIfStat(LSIfStatement s) {
|
||||
writeln( "if ("+eval_bool(s.condition)+") {" );
|
||||
++indent;
|
||||
writeStatements( s.statements );
|
||||
if ( s.elseifs != null ) {
|
||||
for ( LSIfStatement.ElseIf elseif : s.elseifs ) {
|
||||
--indent;
|
||||
writeln( "} else if ("+eval_bool(elseif.condition)+") {" );
|
||||
++indent;
|
||||
writeStatements( elseif.statements );
|
||||
}
|
||||
}
|
||||
if ( s.elsestatements != null ) {
|
||||
--indent;
|
||||
writeln( "} else {" );
|
||||
++indent;
|
||||
writeStatements( s.elsestatements );
|
||||
}
|
||||
--indent;
|
||||
writeln( "}" );
|
||||
}
|
||||
|
||||
//-------------------------------------------
|
||||
// assignment using variables
|
||||
//-------------------------------------------
|
||||
|
||||
/** Write assignment of a particular variable value */
|
||||
private void writeAssign(LSVariable v, String expression) {
|
||||
switch ( v.type ) {
|
||||
case nameVariable: writeNameAssign( (LSVariable.NameReference) v, expression); break;
|
||||
case fieldVariable: writeFieldAssign( (LSVariable.Field) v, expression); break;
|
||||
case methodVariable: writeMethodAssign( (LSVariable.Method) v, expression); break;
|
||||
case parenthesesVariable: writeParenAssign( (LSVariable.Parentheses) v, expression); break;
|
||||
case indexVariable: writeIndexAssign( (LSVariable.Index) v, expression); break;
|
||||
case callFunctionVariable: writeCallFuncAssign((LSVariable.CallFunction)v, expression); break;
|
||||
case callMethodVariable: writeCallMethAssign((LSVariable.CallMethod) v, expression); break;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeNameAssign(NameReference v, String expression) {
|
||||
if ( v.name.isGlobal() )
|
||||
writeln( "env.set(\""+v.name.luaname+"\","+expression+");");
|
||||
else if ( v.name.isupvalue )
|
||||
writeln( javaName(v.name)+"[0]="+expression+";");
|
||||
else
|
||||
writeln( javaName(v.name)+"="+expression+";");
|
||||
}
|
||||
|
||||
private void writeFieldAssign(Field v, String expression) {
|
||||
String base = eval(v.variable);
|
||||
writeln( base+".set(\""+v.field+"\","+expression+");");
|
||||
}
|
||||
|
||||
private void writeMethodAssign(Method v, String expression) {
|
||||
String base = eval(v.variable);
|
||||
writeln( base+".set(\""+v.method+"\","+expression+");");
|
||||
}
|
||||
|
||||
private void writeParenAssign(Parentheses v, String expression) {
|
||||
throw new IllegalArgumentException("no assignment for parenthesis expressions");
|
||||
}
|
||||
|
||||
private void writeIndexAssign(Index v, String expression) {
|
||||
String base = eval(v.variable);
|
||||
writeln( base+".set("+eval(v.expression)+","+expression+");");
|
||||
}
|
||||
|
||||
private void writeCallFuncAssign(CallFunction v, String expression) {
|
||||
throw new IllegalArgumentException("no assignment for call function expressions");
|
||||
}
|
||||
|
||||
private void writeCallMethAssign(CallMethod v, String expression) {
|
||||
throw new IllegalArgumentException("no assignment for call method expressions");
|
||||
}
|
||||
|
||||
//-------------------------------------------
|
||||
// write out expressions
|
||||
//-------------------------------------------
|
||||
|
||||
private String eval_bool(LSExpression e) {
|
||||
return eval(e)+".toboolean()";
|
||||
}
|
||||
|
||||
/** evaluate the expression to a particular operand type */
|
||||
private String eval(LSExpression e) {
|
||||
if ( e==null ) return "NONE";
|
||||
switch ( e.type ) {
|
||||
case nilConstant: return "NIL";
|
||||
case trueConstant: return "TRUE";
|
||||
case falseConstant: return "FALSE";
|
||||
case unop: return evalUnop( (LSExpression.UnopExpr) e);
|
||||
case binop: return evalBinop( (LSExpression.BinopExpr) e);
|
||||
case functionExpr: return evalFunction((LSExpression.FunctionExpr) e);
|
||||
case tableConstructor: return evalTable( (LSExpression.TableConstructor) e);
|
||||
case numberConstant: return evalNumber( (LSExpression.NumberConstant) e);
|
||||
case stringConstant: return evalString( (LSExpression.StringConstant) e);
|
||||
|
||||
// variable types
|
||||
case nameVariable: return evalNameRef( (LSVariable.NameReference) e);
|
||||
case fieldVariable: return evalField( (LSVariable.Field) e);
|
||||
case methodVariable: return evalMethod( (LSVariable.Method) e);
|
||||
case parenthesesVariable: return evalParen( (LSVariable.Parentheses) e);
|
||||
case indexVariable: return evalIndex( (LSVariable.Index) e);
|
||||
case callFunctionVariable: return evalCallFunc((LSVariable.CallFunction) e);
|
||||
case callMethodVariable: return evalCallMeth((LSVariable.CallMethod) e);
|
||||
case varargsRef: return evalVarargs( (LSExpression.VarargsRef) e);
|
||||
|
||||
default: throw new IllegalArgumentException("unknown expression type: "+e.type);
|
||||
}
|
||||
}
|
||||
|
||||
private String evalUnop(UnopExpr e) {
|
||||
switch ( e.op.type ) {
|
||||
case neg: return eval( e.rhs )+".neg()";
|
||||
case not: return eval( e.rhs )+".not()";
|
||||
case len: return eval( e.rhs )+".len()";
|
||||
}
|
||||
throw new IllegalArgumentException("unknown unary operand: "+e.op );
|
||||
}
|
||||
|
||||
private String evalBinop(BinopExpr e) {
|
||||
switch ( e.op.type ) {
|
||||
case pow: return eval(e.lhs)+".pow("+eval(e.rhs)+")";
|
||||
case mul: return eval(e.lhs)+".mul("+eval(e.rhs)+")";
|
||||
case div: return eval(e.lhs)+".div("+eval(e.rhs)+")";
|
||||
case mod: return eval(e.lhs)+".mod("+eval(e.rhs)+")";
|
||||
case add: return eval(e.lhs)+".add("+eval(e.rhs)+")";
|
||||
case sub: return eval(e.lhs)+".sub("+eval(e.rhs)+")";
|
||||
case concat: return eval(e.lhs)+".concat("+eval(e.rhs)+")";
|
||||
case lt: return eval(e.lhs)+".lt("+eval(e.rhs)+")";
|
||||
case lteq: return eval(e.lhs)+".lteq("+eval(e.rhs)+")";
|
||||
case gt: return eval(e.lhs)+".gt("+eval(e.rhs)+")";
|
||||
case gteq: return eval(e.lhs)+".gteq("+eval(e.rhs)+")";
|
||||
case eq: return eval(e.lhs)+".eq("+eval(e.rhs)+")";
|
||||
case neq: return eval(e.lhs)+".neq("+eval(e.rhs)+")";
|
||||
case and: return "(($t="+eval(e.lhs)+").toboolean()? "+eval(e.rhs)+": $t)";
|
||||
case or: return "(($t="+eval(e.lhs)+").toboolean()? $t: "+eval(e.rhs)+")";
|
||||
default: throw new IllegalStateException("unknoqn binary operator: "+e.op);
|
||||
}
|
||||
}
|
||||
|
||||
private String evalFunction(FunctionExpr e) {
|
||||
return evalFuncbody(e.function);
|
||||
}
|
||||
|
||||
private String evalTable(TableConstructor e) {
|
||||
StringBuffer named = new StringBuffer();
|
||||
StringBuffer numbered = new StringBuffer();
|
||||
LSExpression varargsLastListValue = null;
|
||||
for ( int i=0, n=e.fields.size(); i<n; i++ ) {
|
||||
LSField f = e.fields.get(i);
|
||||
switch ( f.type ) {
|
||||
case keyValue:
|
||||
LSField.KeyValue k = (LSField.KeyValue) f;
|
||||
named.append( eval(k.key)+","+eval(k.value)+",");
|
||||
break;
|
||||
case nameValue:
|
||||
LSField.NameValue nv = (LSField.NameValue) f;
|
||||
named.append( "valueOf(\""+nv.name+"\"),"+eval(nv.value)+",");
|
||||
break;
|
||||
case listValue:
|
||||
LSField.ListValue l = (LSField.ListValue) f;
|
||||
int nr = l.value.getNumReturns();
|
||||
if ( i<n-1 && (nr==1) )
|
||||
numbered.append( eval(l.value)+",");
|
||||
else
|
||||
varargsLastListValue = l.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// TODO: generated more targeted constructor
|
||||
return "tableOf("
|
||||
+(named .length()>0? "new LuaValue[] {"+named +"}": "null")+","
|
||||
+(numbered.length()>0? "new LuaValue[] {"+numbered+"}": "null")
|
||||
+(varargsLastListValue!=null? ","+eval(varargsLastListValue): "")+")";
|
||||
}
|
||||
|
||||
private String evalNumber(NumberConstant e) {
|
||||
// TODO: internalize constants
|
||||
return "valueOf("+e.value+")";
|
||||
}
|
||||
|
||||
private String evalString(StringConstant e) {
|
||||
// TODO: internalize constants
|
||||
return "valueOf("+toStrValueInitializer(e.bytes)+")";
|
||||
}
|
||||
|
||||
private String toStrValueInitializer(byte[] bytes) {
|
||||
int n = bytes.length;
|
||||
StringBuffer sb = new StringBuffer(n+2);
|
||||
|
||||
// check for characters beyond ascii 128
|
||||
for ( int i=0; i<n; i++ )
|
||||
if (bytes[i]<0) {
|
||||
sb.append( "new byte[]{" );
|
||||
for ( int j=0; j<n; j++ ) {
|
||||
if ( j>0 ) sb.append(",");
|
||||
byte b = bytes[j];
|
||||
switch ( b ) {
|
||||
case '\n': sb.append( "'\\n'" ); break;
|
||||
case '\r': sb.append( "'\\r'" ); break;
|
||||
case '\t': sb.append( "'\\t'" ); break;
|
||||
case '\\': sb.append( "'\\\\'" ); break;
|
||||
default:
|
||||
if ( b >= ' ' ) {
|
||||
sb.append( '\'');
|
||||
sb.append( (char) b );
|
||||
sb.append( '\'');
|
||||
} else {
|
||||
sb.append( String.valueOf((int)b) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
sb.append( "}" );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
sb.append('"');
|
||||
for ( int i=0; i<n; i++ ) {
|
||||
byte b = bytes[i];
|
||||
switch ( b ) {
|
||||
case '\b': sb.append( "\\b" ); break;
|
||||
case '\f': sb.append( "\\f" ); break;
|
||||
case '\n': sb.append( "\\n" ); break;
|
||||
case '\r': sb.append( "\\r" ); break;
|
||||
case '\t': sb.append( "\\t" ); break;
|
||||
case '"': sb.append( "\\\"" ); break;
|
||||
case '\\': sb.append( "\\\\" ); break;
|
||||
default:
|
||||
if ( b >= ' ' ) {
|
||||
sb.append( (char) b ); break;
|
||||
} else {
|
||||
// convert from UTF-8
|
||||
int u = 0xff & (int) b;
|
||||
if ( u>=0xc0 && i+1<n ) {
|
||||
if ( u>=0xe0 && i+2<n ) {
|
||||
u = ((u & 0xf) << 12) | ((0x3f & bytes[i+1]) << 6) | (0x3f & bytes[i+2]);
|
||||
i+= 2;
|
||||
} else {
|
||||
u = ((u & 0x1f) << 6) | (0x3f & bytes[++i]);
|
||||
}
|
||||
}
|
||||
sb.append( "\\u" );
|
||||
sb.append( Integer.toHexString(0x10000+u).substring(1) );
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.append('"');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
private String evalNameRef(NameReference v) {
|
||||
if ( v.name.isGlobal() )
|
||||
return "env.get(\""+v.name.luaname+"\")";
|
||||
else if ( v.name.isupvalue )
|
||||
return javaName(v.name)+"[0]";
|
||||
else
|
||||
return javaName(v.name);
|
||||
}
|
||||
|
||||
private String evalField(Field e) {
|
||||
return eval(e.variable)+".get(\""+e.field+"\")";
|
||||
}
|
||||
|
||||
private String evalMethod(Method e) {
|
||||
// FIXME: check api, fix this
|
||||
return eval(e.variable)+".get(\""+e.method+"\")";
|
||||
}
|
||||
|
||||
private String evalParen(Parentheses e) {
|
||||
return eval(e.expression)+".arg1()";
|
||||
}
|
||||
|
||||
private String evalIndex(Index e) {
|
||||
return eval(e.variable)+".get("+eval(e.expression)+")";
|
||||
}
|
||||
|
||||
private String evalCallFunc(CallFunction e) {
|
||||
int n = e.parameters.size();
|
||||
boolean isVarargsReturn = e.numReturns < 0 || e.numReturns > 1;
|
||||
boolean isVarargsCall = n>0 && e.parameters.get(n-1).getNumReturns() < 0;
|
||||
String base = eval(e.variable);
|
||||
if ( n <= 3 && !isVarargsReturn && !isVarargsCall ) {
|
||||
return base+".call("+evalParamList(e.parameters)+")";
|
||||
} else {
|
||||
String coerce = e.numReturns==1? ".arg1()": "";
|
||||
switch ( n ) {
|
||||
case 0:
|
||||
return base+".invoke()"+coerce;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
return base+".invoke("+evalParamList(e.parameters)+")"+coerce;
|
||||
default:
|
||||
if ( isVarargsCall ) {
|
||||
LSExpression last = e.parameters.remove(n-1);
|
||||
return base+".invoke(new LuaValue[]{"+evalParamList(e.parameters)+"},"+eval(last)+")"+coerce;
|
||||
} else {
|
||||
return base+".invoke(new LuaValue[]{"+evalParamList(e.parameters)+"})"+coerce;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String evalCallMeth(CallMethod e) {
|
||||
int n = e.parameters.size();
|
||||
String base = eval(e.variable);
|
||||
if ( n <= 3 && e.numReturns == 0 || e.numReturns == 1 ) {
|
||||
return base+".method(\""+e.method+"\""+(e.parameters.size()>0? ",": "")+evalParamList(e.parameters)+")";
|
||||
} else {
|
||||
return base+".invokemethod(\""+e.method+"\",new LuaValue[]{"+evalParamList(e.parameters)+"})";
|
||||
}
|
||||
}
|
||||
|
||||
private String evalVarargs(VarargsRef e) {
|
||||
switch ( e.numReturns ) {
|
||||
case 0: return "NIL";
|
||||
case 1: return "$args.arg1()";
|
||||
default: return "$args";
|
||||
}
|
||||
}
|
||||
|
||||
private String evalParamList(List<LSExpression> parameters) {
|
||||
if ( parameters == null || parameters.size() == 0 )
|
||||
return "";
|
||||
StringBuffer p = new StringBuffer();
|
||||
for ( int i=0, n=parameters.size(); i<n; i++ ) {
|
||||
if (i>0) p.append(",");
|
||||
p.append( eval( parameters.get(i) ) );
|
||||
}
|
||||
return p.toString();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------
|
||||
// write individual strings and lines
|
||||
//-------------------------------------------
|
||||
|
||||
|
||||
private void writeindent() {
|
||||
for ( int i=0; i<indent; i++ )
|
||||
sb.append( " " );
|
||||
}
|
||||
private void write( String str ) {
|
||||
sb.append( str );
|
||||
}
|
||||
private void writeln() {
|
||||
sb.append( '\n' );
|
||||
}
|
||||
private void writeln( String line ) {
|
||||
writeindent();
|
||||
write( line );
|
||||
writeln();
|
||||
}
|
||||
|
||||
}
|
||||
96
src/jse/org/luaj/vm2/luajc/LuaJCompiler.java
Normal file
96
src/jse/org/luaj/vm2/luajc/LuaJCompiler.java
Normal file
@@ -0,0 +1,96 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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 java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.StandardLocation;
|
||||
import javax.tools.ToolProvider;
|
||||
import javax.tools.JavaCompiler.CompilationTask;
|
||||
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.luajc.antlr.AntlrLuaJCompiler;
|
||||
|
||||
public class LuaJCompiler {
|
||||
|
||||
public static LuaValue compile( InputStream luaSource, String chunkName, LuaValue env ) throws Exception {
|
||||
String java = compileToJava( luaSource, chunkName );
|
||||
LuaValue chunk = javaCompile( java, chunkName );
|
||||
chunk.setfenv(env);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public static String compileToJava( InputStream luaSource, String chunkName ) throws Exception {
|
||||
return AntlrLuaJCompiler.compile( luaSource, chunkName );
|
||||
}
|
||||
|
||||
|
||||
public static LuaValue javaCompile( String java, String className) throws Exception {
|
||||
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
if (compiler == null) {
|
||||
LuaValue.error("no java compiler");
|
||||
}
|
||||
|
||||
// write the file
|
||||
new File("jit").mkdirs();
|
||||
File source = new File("jit/"+className+JavaFileObject.Kind.SOURCE.extension);
|
||||
PrintStream ps = new PrintStream(new FileOutputStream(source));
|
||||
ps.print(java);
|
||||
ps.close();
|
||||
|
||||
// set up output location
|
||||
Iterable<? extends File> dest = Arrays.asList(new File[] { new File("bin") });
|
||||
StandardJavaFileManager fm = compiler.getStandardFileManager( null, null, null);
|
||||
fm.setLocation(StandardLocation.CLASS_OUTPUT, dest);
|
||||
|
||||
// compile the file
|
||||
Iterable<? extends JavaFileObject> compilationUnits = fm.getJavaFileObjects(source);
|
||||
CompilationTask task = compiler.getTask(null, fm, null, null, null, compilationUnits);
|
||||
boolean success = task.call();
|
||||
|
||||
// instantiate, config and return
|
||||
if (success) {
|
||||
// compile sub-prototypes
|
||||
// if ( p.p != null ) {
|
||||
// for ( int i=0, n=p.p.length; i<n; i++ ) {
|
||||
// if ( ! (p.p[i] instanceof JitPrototype) )
|
||||
// p.p[i] = jitCompile( p.p[i] );
|
||||
// }
|
||||
// }
|
||||
|
||||
// create JitPrototype instance
|
||||
Class clazz = Class.forName(className);
|
||||
Object instance = clazz.newInstance();
|
||||
LuaValue value = (LuaValue) instance;
|
||||
return value;
|
||||
}
|
||||
return LuaValue.error("compile task failed");
|
||||
}
|
||||
|
||||
}
|
||||
60
src/jse/org/luaj/vm2/luajc/antlr/AntlrLuaJCompiler.java
Normal file
60
src/jse/org/luaj/vm2/luajc/antlr/AntlrLuaJCompiler.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.antlr;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.antlr.runtime.ANTLRInputStream;
|
||||
import org.antlr.runtime.CommonTokenStream;
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
import org.luaj.vm2.luajc.JavaCodeGenerator;
|
||||
import org.luaj.vm2.luajc.antlr.LuaLexer;
|
||||
import org.luaj.vm2.luajc.antlr.LuaParser;
|
||||
import org.luaj.vm2.luajc.lst.LSChunk;
|
||||
|
||||
/**
|
||||
* Implementation of lua-to-java compiler using antlr
|
||||
*/
|
||||
public class AntlrLuaJCompiler {
|
||||
|
||||
private final String chunkname;
|
||||
|
||||
public AntlrLuaJCompiler(String chunkname) {
|
||||
this.chunkname = chunkname;
|
||||
}
|
||||
|
||||
public static String compile(InputStream script, String chunkname) throws RecognitionException, IOException {
|
||||
return new AntlrLuaJCompiler(chunkname).docompile( script );
|
||||
}
|
||||
|
||||
private String docompile(InputStream script) throws RecognitionException, IOException {
|
||||
|
||||
ANTLRInputStream input = new ANTLRInputStream(script);
|
||||
LuaLexer lexer = new LuaLexer(input);
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
LuaParser parser = new LuaParser(tokens);
|
||||
LSChunk chunk = parser.chunk(chunkname);
|
||||
return new JavaCodeGenerator().toJava( chunk );
|
||||
}
|
||||
|
||||
}
|
||||
301
src/jse/org/luaj/vm2/luajc/antlr/Lua.g
Normal file
301
src/jse/org/luaj/vm2/luajc/antlr/Lua.g
Normal file
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Lua 5.1 grammar producing typed parse tree.
|
||||
*
|
||||
* Adapted from the grammar produced by Nicolai Mainiero, May 2007
|
||||
*
|
||||
* see http://www.antlr.org/grammar/list
|
||||
*/
|
||||
|
||||
grammar Lua;
|
||||
|
||||
options {
|
||||
backtrack=true;
|
||||
}
|
||||
|
||||
@header {
|
||||
package org.luaj.vm2.luajc.antlr;
|
||||
import org.luaj.vm2.luajc.lst.*;
|
||||
}
|
||||
@lexer::header {
|
||||
package org.luaj.vm2.luajc.antlr;
|
||||
}
|
||||
@members {
|
||||
LSChunk CHK = null;
|
||||
}
|
||||
|
||||
chunk [String chunkname] returns [LSChunk c]
|
||||
@init { CHK = new LSChunk(chunkname); }
|
||||
: funcblock[CHK.function] {$c=CHK;}
|
||||
;
|
||||
|
||||
funcblock [LSFunction f]
|
||||
scope { LSFunction func; }
|
||||
@init { $funcblock::func = $f; }
|
||||
: {CHK.pushScope("body");} block {$f.setStatements($block.stats); CHK.popScope("body"); }
|
||||
;
|
||||
|
||||
block returns [List<LSStatement> stats]
|
||||
@init { $stats = new ArrayList<LSStatement>(); }
|
||||
: (stat {$stats.add($stat.s);} (';')?)*
|
||||
(laststat {$stats.add($laststat.s);} (';')?)?
|
||||
;
|
||||
|
||||
stat returns [LSStatement s]
|
||||
@init { Name name=null; List<Name> names=null; }
|
||||
: varlist1 '=' explist1 { $s=LSStatement.varAssignStatement($varlist1.vars,$explist1.exprs, CHK.peekScope(), $funcblock::func); }
|
||||
| functioncall { $s=LSStatement.functionCallStatement($functioncall.v); }
|
||||
| 'do' {CHK.pushScope("do");} block {CHK.popScope("do");} 'end'
|
||||
{ $s=LSStatement.doBlockStatement($block.stats); }
|
||||
| 'while' exp 'do' {CHK.pushScope("while");} block {CHK.popScope("while");} 'end'
|
||||
{ $s=LSStatement.whileLoopStatement($exp.e,$block.stats); }
|
||||
| 'repeat' {CHK.pushScope("repeat");} block {CHK.popScope("repeat");} 'until' exp
|
||||
{ $s=LSStatement.repeatUntilStatement($block.stats,$exp.e); }
|
||||
| ifstat { $s=$ifstat.s; }
|
||||
| 'for' {CHK.pushScope("fori");} NAME {name=CHK.declare($NAME.text);} '=' e1=exp ',' e2=exp (',' e3=exp)? 'do' {CHK.pushScope("foriblock");} block {CHK.popScope("foriblock");} 'end'
|
||||
{ $s=LSStatement.forLoopStatement(name,$e1.e,$e2.e,$e3.e,$block.stats,CHK.peekScope()); CHK.popScope("fori"); }
|
||||
| 'for' {CHK.pushScope("for");} namelist {names=CHK.declare($namelist.names);} 'in' explist1 'do' {CHK.pushScope("forblock");} block {CHK.popScope("forblock");}'end'
|
||||
{ $s=LSStatement.forListStatement(names,$explist1.exprs,$block.stats,CHK.peekScope(), $funcblock::func); CHK.popScope("for");}
|
||||
| 'function' funcname funcbody { $s=LSStatement.varFunctionStatement($funcname.v,$funcbody.f); }
|
||||
| 'local' 'function' NAME {name=CHK.declare($NAME.text);} funcbody
|
||||
{ $s=LSStatement.localFunctionStatement(name,$funcbody.f); }
|
||||
| 'local' namelist ('=' explist1)? { $s=LSStatement.localAssignStatement(CHK.declare($namelist.names),$explist1.exprs,CHK.peekScope(), $funcblock::func); }
|
||||
;
|
||||
|
||||
ifstat returns [LSStatement s]
|
||||
scope { LSIfStatement current; }
|
||||
: 'if' e1=exp 'then' {CHK.pushScope("if");} b1=block {$ifstat::current=new LSIfStatement($e1.e,$b1.stats); CHK.popScope("if");}
|
||||
('elseif' e2=exp 'then' {CHK.pushScope("elseif");} b2=block {$ifstat::current.addElseif($e2.e,$b2.stats); CHK.popScope("elseif");})*
|
||||
('else' {CHK.pushScope("else");} b3=block {$ifstat::current.addElse($b3.stats); CHK.popScope("else");})?
|
||||
'end'
|
||||
{ $s=$ifstat::current; }
|
||||
;
|
||||
|
||||
laststat returns [LSStatement s]
|
||||
: 'return' (e=explist1)? {$s=LSStatement.returnStatement($funcblock::func,$e.exprs);}
|
||||
| 'break' {$s=LSStatement.breakStatement();}
|
||||
;
|
||||
|
||||
funcname returns [LSVariable v]
|
||||
: n=NAME {$v = LSVariable.nameVariable(CHK.reference($n.text,$funcblock::func));}
|
||||
('.' n2=NAME {$v = $v.fieldVariable($n2.text);})*
|
||||
(':' n3=NAME {$v = $v.methodVariable($n3.text);})?
|
||||
;
|
||||
|
||||
varlist1 returns [List<LSVariable> vars]
|
||||
@init { $vars = new ArrayList<LSVariable>(); }
|
||||
: v1=var {$vars.add($v1.v);}
|
||||
(',' v2=var {$vars.add($v2.v);})*
|
||||
;
|
||||
|
||||
namelist returns [List<String> names]
|
||||
: n=NAME {$names=new ArrayList<String>(); $names.add($n.text);}
|
||||
(',' n2=NAME {$names.add($n2.text);})*
|
||||
;
|
||||
|
||||
explist1 returns [List<LSExpression> exprs]
|
||||
@init { $exprs = new ArrayList<LSExpression>(); }
|
||||
: (e1=exp ',' {$exprs.add($e1.e);})*
|
||||
e2=exp {$exprs.add($e2.e);}
|
||||
;
|
||||
|
||||
exp returns [LSExpression e]
|
||||
: ('nil' { $e=LSExpression.ENIL; }
|
||||
| 'false' { $e=LSExpression.EFALSE; }
|
||||
| 'true' { $e=LSExpression.ETRUE; }
|
||||
| number { $e=LSExpression.numberExpression($number.text); }
|
||||
| string { $e=$string.e; }
|
||||
| '...' { $e=LSExpression.varargsRef(); $funcblock::func.setUsesVarargs(); }
|
||||
| function { $e=LSExpression.functionExpression($function.f); }
|
||||
| prefixexp { $e=$prefixexp.v; }
|
||||
| tableconstructor { $e=$tableconstructor.e;}
|
||||
| unop e1=exp { $e=LSExpression.unopExpression($unop.op,$e1.e,CHK.peekScope());}
|
||||
) (binop e2=exp { $e=LSExpression.binopExpression($e,$binop.op,$e2.e,CHK.peekScope());})*
|
||||
;
|
||||
|
||||
var returns [LSVariable v]
|
||||
scope { LSVariable current; }
|
||||
: (n=NAME {$var::current=LSVariable.nameVariable(CHK.reference($n.text,$funcblock::func));}
|
||||
| '(' exp ')' {$var::current=LSVariable.parenthesesVariable($exp.e);} varSuffix)
|
||||
varSuffix*
|
||||
{$v=$var::current;}
|
||||
;
|
||||
|
||||
varSuffix
|
||||
: (n=nameAndArgs[$var::current] {$var::current=$n.v;})*
|
||||
('[' e=exp ']' {$var::current=$var::current.indexVariable($e.e);}
|
||||
| '.' n2=NAME {$var::current=$var::current.fieldVariable($n2.text);}
|
||||
)
|
||||
;
|
||||
|
||||
prefixexp returns [LSVariable v]
|
||||
scope { LSVariable current; }
|
||||
: e=varOrExp {$prefixexp::current=$e.v;}
|
||||
(n=nameAndArgs[$prefixexp::current] {$prefixexp::current=$n.v;})*
|
||||
{$v=$prefixexp::current;}
|
||||
;
|
||||
|
||||
functioncall returns [LSVariable v]
|
||||
scope { LSVariable current; }
|
||||
: e=varOrExp {$functioncall::current=$e.v;}
|
||||
(n=nameAndArgs[$functioncall::current] {$functioncall::current=$n.v;})+
|
||||
{$v=$functioncall::current;}
|
||||
;
|
||||
|
||||
varOrExp returns [LSVariable v]
|
||||
: var {$v=$var.v;}
|
||||
| '(' exp ')' {$v=LSVariable.parenthesesVariable($exp.e);}
|
||||
;
|
||||
|
||||
nameAndArgs [LSVariable vin] returns [LSVariable v]
|
||||
@init { String method=null; }
|
||||
: (':' n=NAME {method=$n.text;})?
|
||||
a=args {$v=((method==null)?
|
||||
$vin.callFuncVariable($a.exprs):
|
||||
$vin.callMethVariable(method,$a.exprs));}
|
||||
;
|
||||
|
||||
args returns [List<LSExpression> exprs]
|
||||
@init { $exprs = new ArrayList<LSExpression>(); }
|
||||
: '(' (e=explist1 {$exprs=$e.exprs;})? ')'
|
||||
| t=tableconstructor {$exprs.add($t.e);}
|
||||
| s=string {$exprs.add($s.e);}
|
||||
;
|
||||
|
||||
function returns [LSFunction f]
|
||||
: 'function' b=funcbody {$f = $b.f;}
|
||||
;
|
||||
|
||||
funcbody returns [LSFunction f]
|
||||
@init {
|
||||
$f = new LSFunction();
|
||||
$funcblock::func.functions.add($f);
|
||||
}
|
||||
: {CHK.pushScope("func",true);} '(' (parlist1 [f])? ')' funcblock[f] 'end' {CHK.popScope("func");}
|
||||
;
|
||||
|
||||
parlist1 [LSFunction f]
|
||||
: namelist {f.setParameterNames(CHK.declare($namelist.names));} (',' '...' {f.isvararg=true;})?
|
||||
| '...' {f.isvararg=true;}
|
||||
;
|
||||
|
||||
tableconstructor returns [LSExpression e]
|
||||
@init { List<LSField> fields = new ArrayList<LSField>(); }
|
||||
: '{' (fieldlist[fields])? '}' {$e=LSExpression.tableConstructorExpression(fields);}
|
||||
;
|
||||
|
||||
fieldlist [List<LSField> fields]
|
||||
: field [fields] (fieldsep field [fields])* (fieldsep)?
|
||||
;
|
||||
|
||||
field [List<LSField> fields]
|
||||
: '[' k=exp ']' '=' e=exp {$fields.add(LSField.keyValueField($k.e,$e.e));}
|
||||
| n=NAME '=' e=exp {$fields.add(LSField.nameValueField($n.text,$e.e));}
|
||||
| e=exp {$fields.add(LSField.valueField($e.e));}
|
||||
;
|
||||
|
||||
fieldsep
|
||||
: ','
|
||||
| ';'
|
||||
;
|
||||
|
||||
binop returns [BinOp op]
|
||||
: '+' {$op=BinOp.ADD;}
|
||||
| '-' {$op=BinOp.SUB;}
|
||||
| '*' {$op=BinOp.MUL;}
|
||||
| '/' {$op=BinOp.DIV;}
|
||||
| '^' {$op=BinOp.POW;}
|
||||
| '%' {$op=BinOp.MOD;}
|
||||
| '..' {$op=BinOp.CONCAT;}
|
||||
| '<' {$op=BinOp.LT;}
|
||||
| '<=' {$op=BinOp.LTEQ;}
|
||||
| '>' {$op=BinOp.GT;}
|
||||
| '>=' {$op=BinOp.GTEQ;}
|
||||
| '==' {$op=BinOp.EQ;}
|
||||
| '~=' {$op=BinOp.NEQ;}
|
||||
| 'and' {$op=BinOp.AND; $funcblock::func.hasandlogic=true;}
|
||||
| 'or' {$op=BinOp.OR; $funcblock::func.hasorlogic=true;}
|
||||
;
|
||||
|
||||
unop returns [UnOp op]
|
||||
: '-' {$op=UnOp.NEG;}
|
||||
| 'not' {$op=UnOp.NOT;}
|
||||
| '#' {$op=UnOp.LEN;}
|
||||
;
|
||||
|
||||
number
|
||||
: ('-')? INT
|
||||
| ('-')? FLOAT1
|
||||
| ('-')? FLOAT2
|
||||
| ('-')? FLOAT3
|
||||
| ('-')? EXP
|
||||
| HEX
|
||||
;
|
||||
|
||||
string returns [LSExpression e]
|
||||
: NORMALSTRING {$e=LSExpression.normalStringExpression($NORMALSTRING.text);}
|
||||
| CHARSTRING {$e=LSExpression.charStringExpression($CHARSTRING.text);}
|
||||
| LONGSTRING {$e=LSExpression.longStringExpression($LONGSTRING.text);}
|
||||
;
|
||||
|
||||
|
||||
// LEXER
|
||||
|
||||
|
||||
NAME :('a'..'z'|'A'..'Z'|'_')(options{greedy=true;}: 'a'..'z'|'A'..'Z'|'_'|'0'..'9')*
|
||||
;
|
||||
|
||||
INT : ('0'..'9')+;
|
||||
|
||||
FLOAT1 :'.' INT ;
|
||||
|
||||
FLOAT2 :INT '.' ;
|
||||
|
||||
FLOAT3 :INT '.' INT ;
|
||||
|
||||
EXP : (INT | FLOAT1 | FLOAT2 | FLOAT3) ('E'|'e') ('-'|'+')? INT;
|
||||
|
||||
HEX :'0' ('x' | 'X') ('0'..'9'| 'a'..'f' | 'A'..'F')+ ;
|
||||
|
||||
|
||||
|
||||
NORMALSTRING
|
||||
: '"' ( EscapeSequence | ~('\\'|'"') )* '"'
|
||||
;
|
||||
|
||||
CHARSTRING
|
||||
: '\'' ( EscapeSequence | ~('\\'|'\'') )* '\''
|
||||
;
|
||||
|
||||
LONGSTRING
|
||||
: '['('=')*'[' ( EscapeSequence | ~('\\'|']') )* ']'('=')*']'
|
||||
;
|
||||
|
||||
fragment
|
||||
EscapeSequence
|
||||
: '\\' ('a'|'b'|'f'|'n'|'r'|'t'|'v'|'\"'|'\''|'\\'|'\n')
|
||||
| DecimalEscape
|
||||
;
|
||||
|
||||
fragment
|
||||
DecimalEscape
|
||||
: '\\' ('0'..'9') (('0'..'9') ('0'..'9')?)?
|
||||
;
|
||||
|
||||
|
||||
COMMENT
|
||||
: '--[[' ( options {greedy=false;} : . )* '--]]' {skip();}
|
||||
| '--[=[' ( options {greedy=false;} : . )* '--]==]' {skip();}
|
||||
| '--[==[' ( options {greedy=false;} : . )* '--]==]' {skip();}
|
||||
| '--[===[' ( options {greedy=false;} : . )* '--]===]' {skip();}
|
||||
;
|
||||
|
||||
LINE_COMMENT
|
||||
: '--' ~('\n'|'\r')* '\r'? '\n' {skip();}
|
||||
;
|
||||
|
||||
|
||||
WS : (' '|'\t'|'\u000C') {skip();}
|
||||
;
|
||||
|
||||
NEWLINE : ('\r')? '\n' {skip();}
|
||||
;
|
||||
110
src/jse/org/luaj/vm2/luajc/antlr/Lua.tokens
Normal file
110
src/jse/org/luaj/vm2/luajc/antlr/Lua.tokens
Normal file
@@ -0,0 +1,110 @@
|
||||
T__66=66
|
||||
T__64=64
|
||||
T__29=29
|
||||
T__65=65
|
||||
T__28=28
|
||||
T__62=62
|
||||
T__27=27
|
||||
T__63=63
|
||||
T__26=26
|
||||
T__25=25
|
||||
T__24=24
|
||||
T__23=23
|
||||
T__22=22
|
||||
T__21=21
|
||||
T__20=20
|
||||
T__61=61
|
||||
T__60=60
|
||||
FLOAT3=8
|
||||
FLOAT2=7
|
||||
FLOAT1=6
|
||||
T__55=55
|
||||
T__56=56
|
||||
T__57=57
|
||||
NAME=4
|
||||
T__58=58
|
||||
T__51=51
|
||||
T__52=52
|
||||
T__53=53
|
||||
T__54=54
|
||||
EXP=9
|
||||
HEX=10
|
||||
T__59=59
|
||||
DecimalEscape=15
|
||||
COMMENT=16
|
||||
T__50=50
|
||||
T__42=42
|
||||
T__43=43
|
||||
T__40=40
|
||||
T__41=41
|
||||
T__46=46
|
||||
T__47=47
|
||||
T__44=44
|
||||
T__45=45
|
||||
LINE_COMMENT=17
|
||||
T__48=48
|
||||
T__49=49
|
||||
CHARSTRING=12
|
||||
INT=5
|
||||
LONGSTRING=13
|
||||
T__30=30
|
||||
NORMALSTRING=11
|
||||
T__31=31
|
||||
T__32=32
|
||||
WS=18
|
||||
T__33=33
|
||||
T__34=34
|
||||
NEWLINE=19
|
||||
T__35=35
|
||||
T__36=36
|
||||
T__37=37
|
||||
T__38=38
|
||||
T__39=39
|
||||
EscapeSequence=14
|
||||
'..'=56
|
||||
'end'=23
|
||||
'#'=66
|
||||
'>='=60
|
||||
'=='=61
|
||||
'/'=53
|
||||
'then'=33
|
||||
'>'=59
|
||||
'repeat'=25
|
||||
';'=20
|
||||
'='=21
|
||||
'return'=36
|
||||
'for'=27
|
||||
'+'=50
|
||||
')'=45
|
||||
'function'=30
|
||||
'.'=38
|
||||
'^'=54
|
||||
'%'=55
|
||||
'do'=22
|
||||
'elseif'=34
|
||||
'true'=42
|
||||
'}'=49
|
||||
'else'=35
|
||||
'and'=63
|
||||
'break'=37
|
||||
'{'=48
|
||||
'...'=43
|
||||
'~='=62
|
||||
'nil'=40
|
||||
'until'=26
|
||||
'<='=58
|
||||
'false'=41
|
||||
'<'=57
|
||||
'if'=32
|
||||
'not'=65
|
||||
':'=39
|
||||
'('=44
|
||||
'or'=64
|
||||
'*'=52
|
||||
'-'=51
|
||||
'['=46
|
||||
'while'=24
|
||||
'local'=31
|
||||
','=28
|
||||
'in'=29
|
||||
']'=47
|
||||
3814
src/jse/org/luaj/vm2/luajc/antlr/LuaLexer.java
Normal file
3814
src/jse/org/luaj/vm2/luajc/antlr/LuaLexer.java
Normal file
File diff suppressed because it is too large
Load Diff
5168
src/jse/org/luaj/vm2/luajc/antlr/LuaParser.java
Normal file
5168
src/jse/org/luaj/vm2/luajc/antlr/LuaParser.java
Normal file
File diff suppressed because it is too large
Load Diff
63
src/jse/org/luaj/vm2/luajc/lst/BinOp.java
Normal file
63
src/jse/org/luaj/vm2/luajc/lst/BinOp.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lst;
|
||||
|
||||
|
||||
public class BinOp {
|
||||
// unary precedence is between POW and MUL
|
||||
public static final int UNARY_PRECEDENCE = 7;
|
||||
|
||||
public enum Type {
|
||||
pow,mul,div,mod,add,sub,concat,lt,lteq,gt,gteq,eq,neq,and,or,
|
||||
}
|
||||
|
||||
public static final BinOp POW = new BinOp(Type.pow, 8, true, "^");
|
||||
public static final BinOp MUL = new BinOp(Type.mul, 6, false, "*");
|
||||
public static final BinOp DIV = new BinOp(Type.div, 6, false, "/");
|
||||
public static final BinOp MOD = new BinOp(Type.mod, 6, false, "%");
|
||||
public static final BinOp ADD = new BinOp(Type.add, 5, false, "+");
|
||||
public static final BinOp SUB = new BinOp(Type.sub, 5, false, "-");
|
||||
public static final BinOp CONCAT = new BinOp(Type.concat, 4, true, "..");
|
||||
public static final BinOp LT = new BinOp(Type.lt, 3, false, "<");
|
||||
public static final BinOp LTEQ = new BinOp(Type.lteq, 3, false, "<=");
|
||||
public static final BinOp GT = new BinOp(Type.gt, 3, false, ">");
|
||||
public static final BinOp GTEQ = new BinOp(Type.gteq, 3, false, ">=");
|
||||
public static final BinOp EQ = new BinOp(Type.eq, 3, false, "==");
|
||||
public static final BinOp NEQ = new BinOp(Type.neq, 3, false, "~=");
|
||||
public static final BinOp AND = new BinOp(Type.and, 2, true, "and");
|
||||
public static final BinOp OR = new BinOp(Type.or, 1, true, "or");
|
||||
|
||||
public final Type type;
|
||||
public final int precedence;
|
||||
public final boolean isrightassoc;
|
||||
public final String luaop;
|
||||
|
||||
private BinOp(Type type, int precedence, boolean isrightassoc, String luaop) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.precedence = precedence;
|
||||
this.isrightassoc = isrightassoc;
|
||||
this.luaop = luaop;
|
||||
}
|
||||
|
||||
public String toString() { return luaop; }
|
||||
}
|
||||
106
src/jse/org/luaj/vm2/luajc/lst/LSChunk.java
Normal file
106
src/jse/org/luaj/vm2/luajc/lst/LSChunk.java
Normal file
@@ -0,0 +1,106 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lst;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/* A Lua Source Chunk */
|
||||
public class LSChunk {
|
||||
public static final boolean SCOPES = System.getProperty("SCOPES")!=null;
|
||||
|
||||
public final String chunkname;
|
||||
public final LSFunction function;
|
||||
public Scope scope;
|
||||
|
||||
public LSChunk( String chunkname ) {
|
||||
this.chunkname = chunkname;
|
||||
this.function = new LSFunction( true );
|
||||
this.scope = null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "@"+chunkname+": "+function;
|
||||
}
|
||||
|
||||
/** push a block scope onto the name scope stack */
|
||||
public void pushScope(String name) {
|
||||
scope = new Scope(scope, false);
|
||||
if(SCOPES)System.out.println(space(scope)+"push "+name+" scope="+scope);
|
||||
|
||||
}
|
||||
|
||||
/** push a function scope onto the name scope stack */
|
||||
public void pushScope(String name,boolean isFunction) {
|
||||
scope = new Scope(scope, isFunction);
|
||||
if(SCOPES)System.out.println(space(scope)+"push "+name+" scope="+scope);
|
||||
}
|
||||
|
||||
/** pop a scope from the scope stack */
|
||||
public Scope popScope(String name) {
|
||||
Scope s = scope;
|
||||
scope = scope.parent;
|
||||
if(SCOPES)System.out.println(space(s)+"pop "+name+" scope="+scope);
|
||||
return s;
|
||||
}
|
||||
|
||||
/** return the current scope */
|
||||
public Scope peekScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
/** Declare a single name in the current scope, and return the Name element for it */
|
||||
public Name declare(String name) {
|
||||
Name n = scope.declare( name );
|
||||
if(SCOPES)System.out.println(space(scope)+" declared "+n+" scope="+scope);
|
||||
return n;
|
||||
}
|
||||
|
||||
/** Declare a list of names in the current scope, and return List of Name for them */
|
||||
public List<Name> declare(List<String> names) {
|
||||
List<Name> results = new ArrayList<Name>(names.size());
|
||||
for ( String s : names )
|
||||
results.add( declare(s) );
|
||||
return results;
|
||||
}
|
||||
|
||||
/** Reference a name, and find either the local scope within the function, the upvalue, or a global name
|
||||
* @param func */
|
||||
public Name reference(String name, LSFunction func) {
|
||||
Name n = scope.reference(name);
|
||||
if ("arg".equals(name) && n.isGlobal() && func.isvararg && !scope.isMainChunkScope()) {
|
||||
n = scope.declare(name);
|
||||
func.setHasArg();
|
||||
}
|
||||
if(SCOPES)System.out.println(space(scope)+" reference "+n+" scope="+scope);
|
||||
return n;
|
||||
}
|
||||
|
||||
/** Print out indentation for a scope */
|
||||
private static final String ws = " ";
|
||||
private String space(Scope i) {
|
||||
return ws.substring(0,i.level*2);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
267
src/jse/org/luaj/vm2/luajc/lst/LSExpression.java
Normal file
267
src/jse/org/luaj/vm2/luajc/lst/LSExpression.java
Normal file
@@ -0,0 +1,267 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lst;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.List;
|
||||
|
||||
public class LSExpression {
|
||||
public enum Type {
|
||||
unop,
|
||||
binop,
|
||||
functionExpr,
|
||||
tableConstructor,
|
||||
nilConstant,
|
||||
trueConstant,
|
||||
falseConstant,
|
||||
varargsRef,
|
||||
numberConstant,
|
||||
stringConstant,
|
||||
|
||||
// variable types
|
||||
nameVariable,
|
||||
fieldVariable,
|
||||
methodVariable,
|
||||
parenthesesVariable,
|
||||
indexVariable,
|
||||
callFunctionVariable,
|
||||
callMethodVariable,
|
||||
}
|
||||
|
||||
public static final LSExpression ENIL = new LSExpression(Type.nilConstant); // nil
|
||||
public static final LSExpression EFALSE = new LSExpression(Type.falseConstant); // false
|
||||
public static final LSExpression ETRUE = new LSExpression(Type.trueConstant); // true
|
||||
|
||||
public final Type type;
|
||||
|
||||
LSExpression(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public static LSExpression functionExpression(LSFunction function) {
|
||||
return new FunctionExpr(function);
|
||||
}
|
||||
|
||||
public static LSExpression unopExpression(UnOp unop, LSExpression rhs, Scope scope) {
|
||||
if ( rhs instanceof BinopExpr ) {
|
||||
BinopExpr b = (BinopExpr) rhs;
|
||||
if ( BinOp.UNARY_PRECEDENCE > b.op.precedence )
|
||||
return binopExpression( unopExpression( unop, b.lhs, scope ), b.op, b.rhs, scope );
|
||||
}
|
||||
return new UnopExpr( unop, rhs );
|
||||
}
|
||||
|
||||
public static LSExpression binopExpression(LSExpression lhs, BinOp binop, LSExpression rhs, Scope scope) {
|
||||
if ( lhs instanceof UnopExpr ) {
|
||||
UnopExpr u = (UnopExpr) lhs;
|
||||
if ( binop.precedence > BinOp.UNARY_PRECEDENCE )
|
||||
return unopExpression( u.op, binopExpression( u.rhs, binop, rhs, scope ), scope );
|
||||
}
|
||||
// TODO: cumulate string concatenations together
|
||||
// TODO: constant folding
|
||||
if ( lhs instanceof BinopExpr ) {
|
||||
BinopExpr b = (BinopExpr) lhs;
|
||||
if ( (binop.precedence > b.op.precedence) ||
|
||||
((binop.precedence == b.op.precedence) && binop.isrightassoc) )
|
||||
return binopExpression( b.lhs, b.op, binopExpression( b.rhs, binop, rhs, scope ), scope );
|
||||
}
|
||||
if ( rhs instanceof BinopExpr ) {
|
||||
BinopExpr b = (BinopExpr) rhs;
|
||||
if ( (binop.precedence > b.op.precedence) ||
|
||||
((binop.precedence == b.op.precedence) && ! binop.isrightassoc) )
|
||||
return binopExpression( binopExpression( lhs, binop, b.lhs, scope ), b.op, b.rhs, scope );
|
||||
}
|
||||
return new BinopExpr( lhs, binop, rhs, scope );
|
||||
}
|
||||
|
||||
public static LSExpression numberExpression(String number) {
|
||||
return new NumberConstant(number);
|
||||
}
|
||||
|
||||
public static LSExpression tableConstructorExpression(List<LSField> fields) {
|
||||
return new TableConstructor( fields );
|
||||
}
|
||||
|
||||
public static LSExpression normalStringExpression(String luaSourceString) {
|
||||
return new StringConstant(luaSourceString.substring(1,luaSourceString.length()-1));
|
||||
}
|
||||
|
||||
public static LSExpression charStringExpression(String luaSourceString) {
|
||||
return new StringConstant(luaSourceString.substring(1,luaSourceString.length()-1));
|
||||
}
|
||||
|
||||
public static LSExpression longStringExpression(String luaSourceString) {
|
||||
luaSourceString = luaSourceString.substring(1,luaSourceString.length()-1);
|
||||
luaSourceString = luaSourceString.substring(luaSourceString.indexOf('[',1)+1, luaSourceString.lastIndexOf(']'));
|
||||
return new StringConstant(luaSourceString);
|
||||
}
|
||||
|
||||
public static LSExpression varargsRef() {
|
||||
return new VarargsRef();
|
||||
}
|
||||
|
||||
/** varargs such as "..." */
|
||||
public static class VarargsRef extends LSExpression {
|
||||
public int numReturns = -1;
|
||||
public VarargsRef() {
|
||||
super( Type.varargsRef );
|
||||
}
|
||||
public void setNumReturns(int i) {
|
||||
this.numReturns = i;
|
||||
}
|
||||
public int getNumReturns() {
|
||||
return numReturns;
|
||||
}
|
||||
public String toString() { return "..."; }
|
||||
}
|
||||
|
||||
/** prefix expression such as "(foo)(bar)" ? */
|
||||
public static class FunctionExpr extends LSExpression {
|
||||
public final LSFunction function;
|
||||
public FunctionExpr( LSFunction function) {
|
||||
super( Type.functionExpr );
|
||||
this.function = function;
|
||||
}
|
||||
public String toString() { return function.toString(); }
|
||||
}
|
||||
|
||||
/** unary operator such as "not foo" */
|
||||
public static class UnopExpr extends LSExpression {
|
||||
public final UnOp op;
|
||||
public final LSExpression rhs;
|
||||
public UnopExpr( UnOp op, LSExpression rhs ) {
|
||||
super( Type.unop );
|
||||
this.op = op;
|
||||
this.rhs = rhs;
|
||||
}
|
||||
public String toString() { return op.luaop+rhs; }
|
||||
}
|
||||
|
||||
/** binary operator such as "a + b" */
|
||||
public static class BinopExpr extends LSExpression {
|
||||
public final LSExpression lhs;
|
||||
public final BinOp op;
|
||||
public final LSExpression rhs;
|
||||
public final Scope scope;
|
||||
public BinopExpr( LSExpression lhs, BinOp op, LSExpression rhs, Scope scope ) {
|
||||
super( Type.binop );
|
||||
this.lhs = lhs;
|
||||
this.op = op;
|
||||
this.rhs = rhs;
|
||||
this.scope = scope;
|
||||
}
|
||||
public String toString() { return lhs+op.luaop+rhs; }
|
||||
}
|
||||
|
||||
/** table constructor such as "{ 'foo', [0]='bar' }" */
|
||||
public static class TableConstructor extends LSExpression {
|
||||
public final List<LSField> fields;
|
||||
public TableConstructor( List<LSField> fields ) {
|
||||
super( Type.tableConstructor );
|
||||
this.fields = fields;
|
||||
int n = fields.size();
|
||||
for ( int i=0; i<n-1; i++ )
|
||||
fields.get(i).setNumReturns(1);
|
||||
if ( n>0 )
|
||||
fields.get(n-1).setNumReturns(-1);
|
||||
}
|
||||
public String toString() { return "{"+fields+"}"; }
|
||||
}
|
||||
|
||||
/** number constants such as '123', "4.56", "0x11fe */
|
||||
public static class NumberConstant extends LSExpression {
|
||||
public final Number value;
|
||||
public NumberConstant( String number ) {
|
||||
super( Type.numberConstant );
|
||||
number = number.toLowerCase();
|
||||
if ( number.startsWith("0x") ) {
|
||||
Long l = Long.parseLong(number.substring(2), 16);
|
||||
value = (l.intValue()==l.longValue()? (Number) Integer.valueOf(l.intValue()): (Number) l);
|
||||
} else {
|
||||
Double d = Double.parseDouble(number);
|
||||
value = (d.doubleValue()==(double)d.intValue()? (Number) Integer.valueOf(d.intValue()): (Number) d);
|
||||
}
|
||||
}
|
||||
public String toString() { return value.toString(); }
|
||||
}
|
||||
|
||||
/** string constants such as 'abc', "def", [[ghi]], and [==[pqr]==] */
|
||||
public static class StringConstant extends LSExpression {
|
||||
public final byte[] bytes;
|
||||
public StringConstant( String luaSourceChars ) {
|
||||
super( Type.stringConstant );
|
||||
this.bytes = unquoteLua( luaSourceChars );
|
||||
}
|
||||
public String toString() { return "\""+new String(bytes)+"\""; }
|
||||
}
|
||||
|
||||
/** Unquote lua quoted sequences, and convert to the bytes represented by the source string. */
|
||||
public static byte[] unquoteLua( String luaSourceChars ) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
char[] c = luaSourceChars.toCharArray();
|
||||
int n = c.length;
|
||||
for ( int i=0; i<n; i++ ) {
|
||||
if ( c[i] == '\\' && i<n ) {
|
||||
switch ( c[++i] ) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
int d=(int) (c[i++]-'0');
|
||||
for ( int j=0; i<n && j<2 && c[i]>='0' && c[i]<='9'; i++, j++ )
|
||||
d = d * 10 + (int) (c[i]-'0');
|
||||
baos.write( (byte) d );
|
||||
--i;
|
||||
continue;
|
||||
case 'a': baos.write( (byte) 7 ); continue;
|
||||
case 'b': baos.write( (byte) '\b' ); continue;
|
||||
case 'f': baos.write( (byte) '\f' ); continue;
|
||||
case 'n': baos.write( (byte) '\n' ); continue;
|
||||
case 'r': baos.write( (byte) '\r' ); continue;
|
||||
case 't': baos.write( (byte) '\t' ); continue;
|
||||
case 'v': baos.write( (byte) 11 ); continue;
|
||||
case '"': baos.write( (byte) '"' ); continue;
|
||||
case '\'': baos.write( (byte) '\'' ); continue;
|
||||
case '\\': baos.write( (byte) '\\' ); continue;
|
||||
default: baos.write( (byte) c[i] ); break;
|
||||
}
|
||||
} else {
|
||||
baos.write( (byte) c[i] );
|
||||
}
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/** Set number of return values, return actual number of returns in practice.
|
||||
*
|
||||
* @param i desired number of returns, or -1 for varargs.
|
||||
*/
|
||||
public void setNumReturns(int i) {
|
||||
}
|
||||
|
||||
/** Get actual number of returns for this subexpression, or -1 for varargs.
|
||||
*
|
||||
* @return actual number of returns, or -1 for varargs.
|
||||
*/
|
||||
public int getNumReturns() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
92
src/jse/org/luaj/vm2/luajc/lst/LSField.java
Normal file
92
src/jse/org/luaj/vm2/luajc/lst/LSField.java
Normal file
@@ -0,0 +1,92 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lst;
|
||||
|
||||
public class LSField {
|
||||
public enum Type {
|
||||
keyValue,
|
||||
nameValue,
|
||||
listValue,
|
||||
}
|
||||
|
||||
public final Type type;
|
||||
|
||||
LSField(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public static LSField keyValueField(LSExpression key, LSExpression value) {
|
||||
return new KeyValue(key, value);
|
||||
}
|
||||
|
||||
public static LSField nameValueField(String name, LSExpression value) {
|
||||
return new NameValue(name, value);
|
||||
}
|
||||
|
||||
public static LSField valueField(LSExpression value) {
|
||||
return new ListValue(value);
|
||||
}
|
||||
|
||||
/** table constructor field with an explicit key index value */
|
||||
public static class KeyValue extends LSField {
|
||||
public final LSExpression key;
|
||||
public final LSExpression value;
|
||||
public KeyValue(LSExpression key, LSExpression value) {
|
||||
super( Type.keyValue );
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
value.setNumReturns(1);
|
||||
}
|
||||
public String toString() { return "["+key+"]="+value; }
|
||||
}
|
||||
|
||||
|
||||
/** table constructor field with an named field for key */
|
||||
public static class NameValue extends LSField {
|
||||
public final String name;
|
||||
public final LSExpression value;
|
||||
public NameValue(String name, LSExpression value) {
|
||||
super( Type.nameValue );
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
value.setNumReturns(1);
|
||||
}
|
||||
public String toString() { return name+"="+value; }
|
||||
}
|
||||
|
||||
/** table constructor field with an implied index key */
|
||||
public static class ListValue extends LSField {
|
||||
public final LSExpression value;
|
||||
public ListValue(LSExpression value) {
|
||||
super( Type.listValue );
|
||||
this.value = value;
|
||||
}
|
||||
public void setNumReturns(int i) {
|
||||
value.setNumReturns(i);
|
||||
}
|
||||
public String toString() { return value.toString(); }
|
||||
}
|
||||
|
||||
public void setNumReturns(int i) {
|
||||
}
|
||||
|
||||
}
|
||||
75
src/jse/org/luaj/vm2/luajc/lst/LSFunction.java
Normal file
75
src/jse/org/luaj/vm2/luajc/lst/LSFunction.java
Normal file
@@ -0,0 +1,75 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lst;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LSFunction {
|
||||
|
||||
public final List<LSStatement> stats = new ArrayList<LSStatement>();
|
||||
public final List<LSFunction> functions = new ArrayList<LSFunction>();
|
||||
public final List<Name> paramnames = new ArrayList<Name>();
|
||||
|
||||
/** set if this is a vararg function */
|
||||
public boolean isvararg;
|
||||
|
||||
/** needsarg is set if the code is vararg and needs the "arg" table to be created. */
|
||||
public boolean hasarg,needsarg;
|
||||
|
||||
/** max number of returns, or -1 for varargs */
|
||||
public int maxReturns = 0;
|
||||
|
||||
/** set if there are logical subexpressions, or varargs assignment */
|
||||
public boolean hasandlogic, hasorlogic, hasvarargassign, usesvarargs;
|
||||
|
||||
public LSFunction() {
|
||||
}
|
||||
|
||||
public LSFunction(boolean isvararg) {
|
||||
this.isvararg = isvararg;
|
||||
}
|
||||
|
||||
public void setStatements(List<LSStatement> stats) {
|
||||
this.stats.clear();
|
||||
this.stats.addAll(stats);
|
||||
}
|
||||
|
||||
public void setParameterNames(List<Name> list) {
|
||||
this.paramnames.clear();
|
||||
this.paramnames.addAll( list );
|
||||
}
|
||||
|
||||
public String toString() { return "function("+paramnames+") "+stats+" end"; }
|
||||
|
||||
public void setUsesVarargs() {
|
||||
this.usesvarargs = true;
|
||||
if ( this.hasarg )
|
||||
this.needsarg = false;
|
||||
}
|
||||
|
||||
public void setHasArg() {
|
||||
this.hasarg = true;
|
||||
if ( ! this.usesvarargs )
|
||||
this.needsarg = true;
|
||||
}
|
||||
}
|
||||
76
src/jse/org/luaj/vm2/luajc/lst/LSIfStatement.java
Normal file
76
src/jse/org/luaj/vm2/luajc/lst/LSIfStatement.java
Normal file
@@ -0,0 +1,76 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lst;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LSIfStatement extends LSStatement {
|
||||
|
||||
public final LSExpression condition;
|
||||
public final List<LSStatement> statements;
|
||||
public List<ElseIf> elseifs;
|
||||
public List<LSStatement> elsestatements;
|
||||
|
||||
public static class ElseIf {
|
||||
public final LSExpression condition;
|
||||
public final List<LSStatement> statements;
|
||||
public ElseIf(LSExpression condition, List<LSStatement> statements) {
|
||||
this.condition = condition;
|
||||
this.statements = statements;
|
||||
}
|
||||
}
|
||||
|
||||
public LSIfStatement(LSExpression condition, List<LSStatement> statements) {
|
||||
super( Type.ifStat );
|
||||
this.condition = condition;
|
||||
this.statements = statements;
|
||||
}
|
||||
|
||||
public void addElseif(LSExpression condition, List<LSStatement> statements) {
|
||||
if ( elseifs == null )
|
||||
elseifs = new ArrayList<ElseIf>();
|
||||
elseifs.add( new ElseIf( condition, statements ) );
|
||||
}
|
||||
|
||||
public void addElse(List<LSStatement> statements) {
|
||||
elsestatements = statements;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "if "+condition+" then "+statements+
|
||||
(elseifs!=null? elseifs.toString(): "")+
|
||||
(elsestatements!=null? " else "+elsestatements: "");
|
||||
}
|
||||
public boolean isNextStatementReachable() {
|
||||
if ( isNextStatementReachable(statements) )
|
||||
return true;
|
||||
if ( elseifs != null )
|
||||
for ( ElseIf e : elseifs )
|
||||
if ( isNextStatementReachable(statements) )
|
||||
return true;
|
||||
if ( isNextStatementReachable(elsestatements) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
327
src/jse/org/luaj/vm2/luajc/lst/LSStatement.java
Normal file
327
src/jse/org/luaj/vm2/luajc/lst/LSStatement.java
Normal file
@@ -0,0 +1,327 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lst;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LSStatement {
|
||||
|
||||
public enum Type {
|
||||
functionCall,
|
||||
doBlock,
|
||||
whileLoop,
|
||||
repeatUntil,
|
||||
varAssign,
|
||||
forLoop,
|
||||
forList,
|
||||
varNamedFunction,
|
||||
localFunction,
|
||||
localAssign,
|
||||
returnStat,
|
||||
breakStat,
|
||||
ifStat,
|
||||
}
|
||||
|
||||
public final Type type;
|
||||
|
||||
LSStatement( Type type ) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public static LSStatement functionCallStatement(LSVariable variable) {
|
||||
return new FunctionCall( variable );
|
||||
}
|
||||
|
||||
public static LSStatement doBlockStatement(List<LSStatement> statements) {
|
||||
return new DoBlock( statements );
|
||||
}
|
||||
|
||||
public static LSStatement whileLoopStatement(LSExpression condition, List<LSStatement> statements) {
|
||||
return new WhileLoop( condition, statements );
|
||||
}
|
||||
|
||||
public static LSStatement repeatUntilStatement(List<LSStatement> statements, LSExpression condition) {
|
||||
return new RepeatUntil( statements, condition );
|
||||
}
|
||||
|
||||
public static LSStatement forLoopStatement(Name name, LSExpression initial,
|
||||
LSExpression limit, LSExpression step, List<LSStatement> statements, Scope scope) {
|
||||
return new ForLoop( name, initial, limit, step, statements, scope );
|
||||
}
|
||||
|
||||
public static LSStatement forListStatement(List<Name> names,
|
||||
List<LSExpression> expressions, List<LSStatement> statements, Scope scope, LSFunction function) {
|
||||
return new ForList( names, expressions, statements, scope, function );
|
||||
}
|
||||
|
||||
public static LSStatement varFunctionStatement(LSVariable funcname, LSFunction funcbody) {
|
||||
return new VarNamedFunction( funcname, funcbody );
|
||||
}
|
||||
|
||||
public static LSStatement localFunctionStatement(Name name, LSFunction funcbody) {
|
||||
return new LocalFunction( name, funcbody );
|
||||
}
|
||||
|
||||
public static LSStatement varAssignStatement(List<LSVariable> variables, List<LSExpression> expressions, Scope scope, LSFunction function) {
|
||||
setExprNumReturns( variables.size(), expressions, function );
|
||||
return new VarAssign( variables, expressions, scope );
|
||||
}
|
||||
|
||||
public static LSStatement localAssignStatement(List<Name> names, List<LSExpression> expressions, Scope scope, LSFunction function) {
|
||||
setExprNumReturns( names.size(), expressions, function );
|
||||
return new LocalAssign( names, expressions, scope );
|
||||
}
|
||||
|
||||
public static void setExprNumReturns( int nassign, List<LSExpression> expressions, LSFunction function ) {
|
||||
int nexpr = expressions!=null? expressions.size(): 0;
|
||||
for ( int i=0; i<nexpr; i++ )
|
||||
expressions.get(i).setNumReturns(
|
||||
(nassign<=nexpr)?
|
||||
(i<nassign? 1: 0): // same or more expressions than names
|
||||
(i<nexpr-1? 1: -1) ); // more names than expressions
|
||||
if ( nassign > nexpr && nexpr > 0 && expressions.get(nexpr-1).getNumReturns() == -1 )
|
||||
function.hasvarargassign = true;
|
||||
}
|
||||
|
||||
public static LSStatement returnStatement(LSFunction function, List<LSExpression> expressions) {
|
||||
int n=expressions!=null? expressions.size(): 0;
|
||||
|
||||
// set num returns of subexpressions
|
||||
for ( int i=0; i<n; i++ )
|
||||
expressions.get(i).setNumReturns(i<n-1? 1: -1); // last in list returns vararg
|
||||
int nreturns = 0;
|
||||
if ( n > 0 ) {
|
||||
LSExpression last = expressions.get(n-1);
|
||||
int lastreturns = last.getNumReturns();
|
||||
nreturns = (lastreturns<0? -1: lastreturns+n-1);
|
||||
}
|
||||
|
||||
// change the containing function to varargs if necessary.
|
||||
if ( function.maxReturns != -1 && function.maxReturns < nreturns )
|
||||
function.maxReturns = nreturns;
|
||||
if ( function.maxReturns == -1 || function.maxReturns > 1 || nreturns < 0 )
|
||||
function.isvararg = true;
|
||||
|
||||
return new ReturnStat( function, expressions );
|
||||
}
|
||||
|
||||
public static LSStatement breakStatement() {
|
||||
return new BreakStat();
|
||||
}
|
||||
|
||||
/** Statement representing a function call on a variable, such as "foo.bar()" */
|
||||
public static final class FunctionCall extends LSStatement {
|
||||
public final LSVariable variable;
|
||||
FunctionCall(LSVariable variable) {
|
||||
super( Type.functionCall );
|
||||
this.variable = variable;
|
||||
}
|
||||
public String toString() { return variable.toString()+"();"; }
|
||||
}
|
||||
|
||||
/** do block, such as "do foo = bar end" */
|
||||
public static final class DoBlock extends LSStatement {
|
||||
public final List<LSStatement> statements;
|
||||
DoBlock(List<LSStatement> statements) {
|
||||
super( Type.doBlock );
|
||||
this.statements = statements;
|
||||
}
|
||||
public String toString() { return "do "+statements+" end;"; }
|
||||
public boolean isNextStatementReachable() {
|
||||
return isNextStatementReachable(statements);
|
||||
}
|
||||
}
|
||||
|
||||
/** while loop, such as "while foo = true do bar() end" */
|
||||
public static final class WhileLoop extends LSStatement {
|
||||
public final LSExpression condition;
|
||||
public final List<LSStatement> statements;
|
||||
WhileLoop(LSExpression condition, List<LSStatement> statements) {
|
||||
super( Type.whileLoop );
|
||||
this.condition = condition;
|
||||
this.statements = statements;
|
||||
}
|
||||
public String toString() { return "while "+condition+" do "+statements+" end;"; }
|
||||
public boolean isNextStatementReachable() {
|
||||
return isNextStatementReachable(statements);
|
||||
}
|
||||
}
|
||||
|
||||
/** repeat loop, such as "repeat foo() until bar == true" */
|
||||
public static final class RepeatUntil extends LSStatement {
|
||||
public final List<LSStatement> statements;
|
||||
public final LSExpression condition;
|
||||
RepeatUntil(List<LSStatement> statements, LSExpression condition) {
|
||||
super( Type.repeatUntil );
|
||||
this.statements = statements;
|
||||
this.condition = condition;
|
||||
}
|
||||
public String toString() { return "repeat "+statements+" until "+condition+";"; }
|
||||
public boolean isNextStatementReachable() {
|
||||
return isNextStatementReachable(statements);
|
||||
}
|
||||
}
|
||||
|
||||
/** assignment to variables, such as "x.a,y.b = foo,bar" */
|
||||
public static final class VarAssign extends LSStatement {
|
||||
public final List<LSVariable> variables;
|
||||
public final List<LSExpression> expressions;
|
||||
public final Scope scope;
|
||||
VarAssign(List<LSVariable> variables, List<LSExpression> expressions, Scope scope) {
|
||||
super( Type.varAssign );
|
||||
this.variables = variables;
|
||||
this.expressions = expressions;
|
||||
this.scope = scope;
|
||||
}
|
||||
public String toString() { return variables+"="+expressions+";"; }
|
||||
}
|
||||
|
||||
/** for loop with index, such as "for i=1,10,2 do ... end" */
|
||||
public static final class ForLoop extends LSStatement {
|
||||
public final Name index;
|
||||
public final LSExpression initial;
|
||||
public final LSExpression limit;
|
||||
public final LSExpression step;
|
||||
public final List<LSStatement> statements;
|
||||
public final Scope scope;
|
||||
ForLoop(Name name, LSExpression initial, LSExpression limit, LSExpression step, List<LSStatement> statements, Scope scope) {
|
||||
super( Type.forLoop );
|
||||
this.index = name;
|
||||
this.initial = initial;
|
||||
this.limit = limit;
|
||||
this.step = step;
|
||||
this.statements = statements;
|
||||
this.scope = scope;
|
||||
initial.setNumReturns(1);
|
||||
limit.setNumReturns(1);
|
||||
if ( step != null )
|
||||
step.setNumReturns(1);
|
||||
}
|
||||
public String toString() { return "for "+index+"="+initial+","+limit+","+step+" do "+statements+" end;"; }
|
||||
public boolean isNextStatementReachable() {
|
||||
return isNextStatementReachable(statements);
|
||||
}
|
||||
}
|
||||
|
||||
/** for loop with variable, such as "for i,j,k in foo() do ... end" */
|
||||
public static final class ForList extends LSStatement {
|
||||
public final List<Name> names;
|
||||
public final List<LSExpression> expressions;
|
||||
public final List<LSStatement> statements;
|
||||
public final Scope scope;
|
||||
ForList(List<Name> names, List<LSExpression> expressions, List<LSStatement> statements, Scope scope, LSFunction function) {
|
||||
super( Type.forList );
|
||||
this.names = names;
|
||||
this.expressions = expressions;
|
||||
this.statements = statements;
|
||||
this.scope = scope;
|
||||
|
||||
// set return value count for each expression in list;
|
||||
int ne = expressions.size();
|
||||
for ( int i=0; i<ne-1 && i<3; i++ )
|
||||
expressions.get(i).setNumReturns(1);
|
||||
if ( ne<=3 ) {
|
||||
expressions.get(ne-1).setNumReturns(3-(ne-1));
|
||||
function.hasvarargassign = true;
|
||||
}
|
||||
}
|
||||
public String toString() { return "for "+names+" in "+expressions+" do "+statements+" end;"; }
|
||||
public boolean isNextStatementReachable() {
|
||||
return isNextStatementReachable(statements);
|
||||
}
|
||||
}
|
||||
|
||||
/** variable function declaration, such as "a.b = function() end" */
|
||||
public static final class VarNamedFunction extends LSStatement {
|
||||
public final LSVariable funcname;
|
||||
public final LSFunction funcbody;
|
||||
VarNamedFunction(LSVariable funcname, LSFunction funcbody) {
|
||||
super( Type.varNamedFunction );
|
||||
this.funcname = funcname;
|
||||
this.funcbody = funcbody;
|
||||
}
|
||||
public String toString() { return funcname+"=f:"+funcbody+";"; }
|
||||
}
|
||||
|
||||
/** simple function declaration, such as "a = function() end" */
|
||||
public static final class LocalFunction extends LSStatement {
|
||||
public final Name name;
|
||||
public final LSFunction funcbody;
|
||||
LocalFunction(Name name, LSFunction funcbody) {
|
||||
super( Type.localFunction );
|
||||
this.name = name;
|
||||
this.funcbody = funcbody;
|
||||
}
|
||||
public String toString() { return name+"=f:"+funcbody+";"; }
|
||||
}
|
||||
|
||||
/** assignment, such as "a,b = foo,bar" */
|
||||
public static final class LocalAssign extends LSStatement {
|
||||
public final List<Name> names;
|
||||
public final List<LSExpression> expressions;
|
||||
public final Scope scope;
|
||||
LocalAssign(List<Name> list, List<LSExpression> expressions, Scope scope) {
|
||||
super( Type.localAssign );
|
||||
this.names = list;
|
||||
this.expressions = expressions;
|
||||
this.scope = scope;
|
||||
}
|
||||
public String toString() { return names+"="+expressions+";"; }
|
||||
}
|
||||
|
||||
/** return statement, such as "return foo,bar" */
|
||||
public static final class ReturnStat extends LSStatement {
|
||||
public final LSFunction function;
|
||||
public final List<LSExpression> expressions;
|
||||
ReturnStat(LSFunction function, List<LSExpression> expressions) {
|
||||
super( Type.returnStat );
|
||||
this.function = function;
|
||||
this.expressions = expressions;
|
||||
}
|
||||
public String toString() { return "return "+expressions+";"; }
|
||||
public boolean isNextStatementReachable() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** break statement */
|
||||
public static final class BreakStat extends LSStatement {
|
||||
BreakStat() {
|
||||
super( Type.breakStat );
|
||||
}
|
||||
public String toString() { return "break;"; }
|
||||
}
|
||||
|
||||
/** True of this statment could return and therefore the next statement is reachable. */
|
||||
public boolean isNextStatementReachable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isNextStatementReachable(List<LSStatement> stats) {
|
||||
if ( stats == null )
|
||||
return true;
|
||||
for ( LSStatement s : stats )
|
||||
if ( ! s.isNextStatementReachable() )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
172
src/jse/org/luaj/vm2/luajc/lst/LSVariable.java
Normal file
172
src/jse/org/luaj/vm2/luajc/lst/LSVariable.java
Normal file
@@ -0,0 +1,172 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lst;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LSVariable extends LSExpression {
|
||||
|
||||
LSVariable(Type type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
/** name, such as 'foo' */
|
||||
public static LSVariable nameVariable(Name name) {
|
||||
return new NameReference(name);
|
||||
}
|
||||
|
||||
/** table field, such as 'a.b' */
|
||||
public LSVariable fieldVariable(String field) {
|
||||
return new Field(this, field);
|
||||
}
|
||||
|
||||
/** method reference, such as foo:bar */
|
||||
public LSVariable methodVariable(String method) {
|
||||
return new Method(this, method);
|
||||
}
|
||||
|
||||
/** parenthetical reference, such as '(foo())' */
|
||||
public static LSVariable parenthesesVariable(LSExpression expression) {
|
||||
if ( expression != null )
|
||||
expression.setNumReturns(1);
|
||||
return new Parentheses(expression);
|
||||
}
|
||||
|
||||
/** table index, such as 'a[b]' */
|
||||
public LSVariable indexVariable(LSExpression expression) {
|
||||
return new Index(this, expression);
|
||||
}
|
||||
|
||||
/** Variable is a method, such as 'a(x,y)' */
|
||||
public LSVariable callFuncVariable(List<LSExpression> parameters) {
|
||||
int n = parameters.size();
|
||||
for ( int i=0; i<n; i++ )
|
||||
parameters.get(i).setNumReturns(i<n-1? 1: -1);
|
||||
return new CallFunction(this, parameters);
|
||||
}
|
||||
|
||||
/** Variable is a method, such as 'a:b(x,y)' */
|
||||
public LSVariable callMethVariable(String method, List<LSExpression> parameters) {
|
||||
int n = parameters.size();
|
||||
for ( int i=0; i<n; i++ )
|
||||
parameters.get(i).setNumReturns(i<n-1? 1: -1);
|
||||
return new CallMethod(this, method, parameters);
|
||||
}
|
||||
|
||||
/** name, such as 'foo' */
|
||||
public static class NameReference extends LSVariable {
|
||||
public final Name name;
|
||||
public NameReference(Name name) {
|
||||
super( Type.nameVariable );
|
||||
this.name = name;
|
||||
}
|
||||
public String toString() { return name.toString(); }
|
||||
}
|
||||
|
||||
/** field reference, such as foo.bar */
|
||||
public static class Field extends LSVariable {
|
||||
public final LSVariable variable;
|
||||
public final String field;
|
||||
public Field(LSVariable variable, String field) {
|
||||
super( Type.fieldVariable );
|
||||
this.variable = variable;
|
||||
this.field = field;
|
||||
}
|
||||
public String toString() { return variable+"."+field; }
|
||||
}
|
||||
|
||||
/** method reference, such as foo:bar */
|
||||
public static class Method extends LSVariable {
|
||||
public final LSVariable variable;
|
||||
public final String method;
|
||||
public Method(LSVariable variable, String method) {
|
||||
super( Type.methodVariable );
|
||||
this.variable = variable;
|
||||
this.method = method;
|
||||
}
|
||||
public String toString() { return variable+":"+method; }
|
||||
}
|
||||
|
||||
/** parenthetical reference, such as '(foo())' */
|
||||
public static class Parentheses extends LSVariable {
|
||||
public final LSExpression expression;
|
||||
public Parentheses(LSExpression expression) {
|
||||
super( Type.parenthesesVariable );
|
||||
this.expression = expression;
|
||||
}
|
||||
public String toString() { return "("+expression+")"; }
|
||||
}
|
||||
|
||||
/** table index, such as 'a[b]' */
|
||||
public static class Index extends LSVariable {
|
||||
public final LSVariable variable;
|
||||
public final LSExpression expression;
|
||||
public Index(LSVariable variable, LSExpression expression) {
|
||||
super( Type.indexVariable );
|
||||
this.variable = variable;
|
||||
this.expression = expression;
|
||||
}
|
||||
public String toString() { return variable+"["+expression+"]"; }
|
||||
}
|
||||
|
||||
|
||||
/** Variable is a function invocation, such as 'a(x,y)' */
|
||||
public static class CallFunction extends LSVariable {
|
||||
public final LSVariable variable;
|
||||
public final List<LSExpression> parameters;
|
||||
public int numReturns = 0;
|
||||
public CallFunction(LSVariable variable, List<LSExpression> parameters) {
|
||||
super( Type.callFunctionVariable );
|
||||
this.variable = variable;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
public void setNumReturns(int i) {
|
||||
this.numReturns = i;
|
||||
}
|
||||
public int getNumReturns() {
|
||||
return numReturns;
|
||||
}
|
||||
public String toString() { return variable+"("+parameters+")"; }
|
||||
}
|
||||
|
||||
/** Variable is a method invocation, such as 'a:bc()' */
|
||||
public static class CallMethod extends LSVariable {
|
||||
public final LSVariable variable;
|
||||
public final String method;
|
||||
public final List<LSExpression> parameters;
|
||||
public int numReturns = 0;
|
||||
public CallMethod(LSVariable variable, String method, List<LSExpression> parameters) {
|
||||
super( Type.callMethodVariable );
|
||||
this.variable = variable;
|
||||
this.method = method;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
public void setNumReturns(int i) {
|
||||
this.numReturns = i;
|
||||
}
|
||||
public int getNumReturns() {
|
||||
return numReturns;
|
||||
}
|
||||
public String toString() { return variable+":"+method+"("+parameters+")"; }
|
||||
}
|
||||
|
||||
}
|
||||
73
src/jse/org/luaj/vm2/luajc/lst/Name.java
Normal file
73
src/jse/org/luaj/vm2/luajc/lst/Name.java
Normal file
@@ -0,0 +1,73 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lst;
|
||||
|
||||
/** A name in lua source, which resolves to one of:
|
||||
* - global reference
|
||||
* - local that is not an upvalue
|
||||
* - local that is an upvalue
|
||||
*/
|
||||
public class Name {
|
||||
|
||||
/** Name in lua source file */
|
||||
public final String luaname;
|
||||
|
||||
/** 0 if in outermost scope, 1 if in next inner scope, ect. */
|
||||
public final int scopelevel;
|
||||
|
||||
/** 0 if first declaration in global program, 1 if second use, etc. */
|
||||
public final int outerrevision;
|
||||
|
||||
/** 0 if first declaration in nearest enclosing function, 1 if second use, etc */
|
||||
public final int innerrevision;
|
||||
|
||||
/** true if used as an upvalue by some enclosed function */
|
||||
public boolean isupvalue;
|
||||
|
||||
/** Construct a name instance */
|
||||
public Name(String luaname, int scopelevel, int outerrevision, int innterrevision) {
|
||||
super();
|
||||
this.luaname = luaname;
|
||||
this.scopelevel = scopelevel;
|
||||
this.outerrevision = outerrevision;
|
||||
this.innerrevision = innterrevision;
|
||||
}
|
||||
|
||||
/** Construct a name reference representing a global reference */
|
||||
public Name(String name) {
|
||||
this.luaname = name;
|
||||
this.scopelevel = -1;
|
||||
this.outerrevision = -1;
|
||||
this.innerrevision = -1;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return scopelevel<0?
|
||||
"_G$"+luaname:
|
||||
luaname+"$s"+scopelevel+"$v"+outerrevision+"$f"+innerrevision;
|
||||
}
|
||||
|
||||
public boolean isGlobal() {
|
||||
return -1 == outerrevision;
|
||||
}
|
||||
|
||||
}
|
||||
103
src/jse/org/luaj/vm2/luajc/lst/Scope.java
Normal file
103
src/jse/org/luaj/vm2/luajc/lst/Scope.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lst;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/** A name scope in lua source terms.
|
||||
* Combination of function scope and block scope.
|
||||
*/
|
||||
public class Scope {
|
||||
public final Scope parent;
|
||||
public final int level;
|
||||
public final boolean isFunctionScope;
|
||||
public boolean hasAndOrLogic;
|
||||
public final Map<String,Name> names = new HashMap<String,Name>();
|
||||
|
||||
/** Construct a new default scope for a chunk */
|
||||
public Scope() {
|
||||
this.parent = null;
|
||||
this.isFunctionScope = true;
|
||||
this.level = 0;
|
||||
}
|
||||
|
||||
/** Construct an inner scope
|
||||
* @param parent the outer scope to fall back to, or null if a global scope
|
||||
* @param isFunctionScope true if this is a function scope, false otherwise
|
||||
*/
|
||||
public Scope(Scope parent, boolean isFunctionScope) {
|
||||
this.parent = parent;
|
||||
this.isFunctionScope = isFunctionScope;
|
||||
this.level = parent!=null? parent.level + 1: 0;
|
||||
}
|
||||
|
||||
/** Declare a single name in the current scope, and return the Name element for it */
|
||||
public Name declare(String name) {
|
||||
boolean crossesFunctionBoundary = false;
|
||||
for ( Scope s=this; s!=null; s=s.parent ) {
|
||||
Name n = s.names.get(name);
|
||||
if ( n != null ) {
|
||||
Name result = new Name(name,
|
||||
level,
|
||||
n.outerrevision+1,
|
||||
crossesFunctionBoundary? 0: n.innerrevision+1);
|
||||
names.put(name, result);
|
||||
return result;
|
||||
}
|
||||
if ( s.isFunctionScope )
|
||||
crossesFunctionBoundary = true;
|
||||
}
|
||||
Name result = new Name(name, level, 0, 0);
|
||||
names.put(name, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Reference a name, and find either the local scope within the function, the upvalue, or a global name */
|
||||
public Name reference(String name) {
|
||||
boolean crossesFunctionBoundary = false;
|
||||
for ( Scope s=this; s!=null; s=s.parent ) {
|
||||
Name n = s.names.get(name);
|
||||
if ( n != null ) {
|
||||
if ( crossesFunctionBoundary ) {
|
||||
n.isupvalue = true;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
if ( s.isFunctionScope )
|
||||
crossesFunctionBoundary = true;
|
||||
}
|
||||
// globally scoped name
|
||||
return new Name(name);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String ours = (isFunctionScope? "F": "")+names;
|
||||
return (parent==null? ours: ours+"->"+parent.toString());
|
||||
}
|
||||
|
||||
/** Return true iff this scope is part the main chunk */
|
||||
public boolean isMainChunkScope() {
|
||||
return isFunctionScope? false: parent==null? true: parent.isMainChunkScope();
|
||||
}
|
||||
}
|
||||
|
||||
43
src/jse/org/luaj/vm2/luajc/lst/UnOp.java
Normal file
43
src/jse/org/luaj/vm2/luajc/lst/UnOp.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.lst;
|
||||
|
||||
public class UnOp {
|
||||
public enum Type {
|
||||
neg,not,len
|
||||
}
|
||||
|
||||
public static final UnOp NEG = new UnOp(Type.neg, "-");
|
||||
public static final UnOp NOT = new UnOp(Type.not, "~");
|
||||
public static final UnOp LEN = new UnOp(Type.len, "#");
|
||||
|
||||
public final Type type;
|
||||
public final String luaop;
|
||||
|
||||
private UnOp(Type type, String luaop) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.luaop = luaop;
|
||||
}
|
||||
|
||||
public String toString() { return luaop; }
|
||||
}
|
||||
303
src/jse/org/luaj/vm2/script/LuaScriptEngine.java
Normal file
303
src/jse/org/luaj/vm2/script/LuaScriptEngine.java
Normal file
@@ -0,0 +1,303 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2008 LuaJ. 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.script;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.Compilable;
|
||||
import javax.script.CompiledScript;
|
||||
import javax.script.ScriptContext;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineFactory;
|
||||
import javax.script.ScriptException;
|
||||
import javax.script.SimpleScriptContext;
|
||||
|
||||
import org.luaj.vm2.LoadState;
|
||||
import org.luaj.vm2.Lua;
|
||||
import org.luaj.vm2.LuaClosure;
|
||||
import org.luaj.vm2.LuaError;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.Prototype;
|
||||
import org.luaj.vm2.compiler.LuaC;
|
||||
import org.luaj.vm2.lib.JsePlatform;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jim_roseborough
|
||||
*/
|
||||
public class LuaScriptEngine implements ScriptEngine, Compilable {
|
||||
|
||||
private static final String __ENGINE_VERSION__ = Lua._VERSION;
|
||||
private static final String __NAME__ = "Luaj";
|
||||
private static final String __SHORT_NAME__ = "Luaj";
|
||||
private static final String __LANGUAGE__ = "lua";
|
||||
private static final String __LANGUAGE_VERSION__ = "5.1";
|
||||
private static final String __ARGV__ = "arg";
|
||||
private static final String __FILENAME__ = "?";
|
||||
|
||||
static {
|
||||
LuaC.install();
|
||||
}
|
||||
|
||||
private static final ScriptEngineFactory myFactory = new LuaScriptEngineFactory();
|
||||
|
||||
private ScriptContext defaultContext;
|
||||
|
||||
private final LuaValue _G;
|
||||
|
||||
public LuaScriptEngine() {
|
||||
|
||||
// create globals
|
||||
_G = JsePlatform.standardGlobals();
|
||||
|
||||
// set up context
|
||||
ScriptContext ctx = new SimpleScriptContext();
|
||||
ctx.setBindings(createBindings(), ScriptContext.ENGINE_SCOPE);
|
||||
setContext(ctx);
|
||||
|
||||
// set special values
|
||||
put(LANGUAGE_VERSION, __LANGUAGE_VERSION__);
|
||||
put(LANGUAGE, __LANGUAGE__);
|
||||
put(ENGINE, __NAME__);
|
||||
put(ENGINE_VERSION, __ENGINE_VERSION__);
|
||||
put(ARGV, __ARGV__);
|
||||
put(FILENAME, __FILENAME__);
|
||||
put(NAME, __SHORT_NAME__);
|
||||
put("THREADING", null);
|
||||
}
|
||||
|
||||
|
||||
public Object eval(String script) throws ScriptException {
|
||||
return eval(new StringReader(script));
|
||||
}
|
||||
|
||||
public Object eval(String script, ScriptContext context) throws ScriptException {
|
||||
return eval(new StringReader(script), context);
|
||||
}
|
||||
|
||||
public Object eval(String script, Bindings bindings) throws ScriptException {
|
||||
return eval(new StringReader(script), bindings);
|
||||
}
|
||||
|
||||
public Object eval(Reader reader) throws ScriptException {
|
||||
return eval(reader, getContext());
|
||||
}
|
||||
|
||||
public Object eval(Reader reader, ScriptContext scriptContext) throws ScriptException {
|
||||
return compile(reader).eval(scriptContext);
|
||||
}
|
||||
|
||||
public Object eval(Reader reader, Bindings bindings) throws ScriptException {
|
||||
ScriptContext c = getContext();
|
||||
Bindings current = c.getBindings(ScriptContext.ENGINE_SCOPE);
|
||||
c.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
|
||||
Object result = eval(reader);
|
||||
c.setBindings(current, ScriptContext.ENGINE_SCOPE);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void put(String key, Object value) {
|
||||
Bindings b = getBindings(ScriptContext.ENGINE_SCOPE);
|
||||
((LuaBindings)b).put(key, value);
|
||||
}
|
||||
|
||||
public Object get(String key) {
|
||||
Bindings b = getBindings(ScriptContext.ENGINE_SCOPE);
|
||||
return ((LuaBindings)b).get(key);
|
||||
}
|
||||
|
||||
public Bindings getBindings(int scope) {
|
||||
return getContext().getBindings(scope);
|
||||
}
|
||||
|
||||
public void setBindings(Bindings bindings, int scope) {
|
||||
getContext().setBindings(bindings, scope);
|
||||
}
|
||||
|
||||
public Bindings createBindings() {
|
||||
return new LuaBindings( _G );
|
||||
}
|
||||
|
||||
public ScriptContext getContext() {
|
||||
return defaultContext;
|
||||
}
|
||||
|
||||
public void setContext(ScriptContext context) {
|
||||
defaultContext = context;
|
||||
}
|
||||
|
||||
public ScriptEngineFactory getFactory() {
|
||||
return myFactory;
|
||||
}
|
||||
|
||||
public CompiledScript compile(String script) throws ScriptException {
|
||||
return compile(new StringReader(script));
|
||||
}
|
||||
|
||||
public CompiledScript compile(Reader reader) throws ScriptException {
|
||||
try {
|
||||
InputStream ris = new Utf8Encoder(reader);
|
||||
try {
|
||||
final Prototype p = LoadState.undump(ris, "script");
|
||||
return new CompiledScript() {
|
||||
public Object eval(ScriptContext context) throws ScriptException {
|
||||
Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE);
|
||||
LuaBindings lb = (LuaBindings) b;
|
||||
LuaClosure c = new LuaClosure( p, lb.env );
|
||||
return c.call();
|
||||
}
|
||||
public ScriptEngine getEngine() {
|
||||
return LuaScriptEngine.this;
|
||||
}
|
||||
};
|
||||
} catch ( LuaError lee ) {
|
||||
throw new ScriptException(lee.getMessage() );
|
||||
} finally {
|
||||
ris.close();
|
||||
}
|
||||
} catch ( Throwable t ) {
|
||||
throw new ScriptException("eval threw "+t.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// ------ lua bindings -----
|
||||
private static final class LuaBindings implements Bindings {
|
||||
private LuaValue env;
|
||||
private LuaValue mt;
|
||||
private LuaBindings( LuaValue _G ) {
|
||||
mt = LuaValue.tableOf();
|
||||
mt.set( LuaValue.INDEX, _G );
|
||||
clear();
|
||||
}
|
||||
public void clear() {
|
||||
env = LuaValue.tableOf();
|
||||
env.setmetatable(mt);
|
||||
}
|
||||
private Object toJava(LuaValue v) {
|
||||
switch ( v.type() ) {
|
||||
case LuaValue.TNIL: return null;
|
||||
case LuaValue.TSTRING: return v.toString();
|
||||
case LuaValue.TUSERDATA: return v.checkuserdata(Object.class);
|
||||
case LuaValue.TNUMBER: return v.isinttype()? new Integer(v.toint()): new Double(v.todouble());
|
||||
default:
|
||||
throw new java.lang.UnsupportedOperationException(
|
||||
"LuaBindings cannot convert lua type '"+v.typename()+"' to Java");
|
||||
}
|
||||
}
|
||||
private LuaValue toLua(Object javaValue) {
|
||||
if ( javaValue instanceof Number ) {
|
||||
return LuaValue.valueOf(((Number)javaValue).doubleValue());
|
||||
} else if ( javaValue instanceof String ) {
|
||||
return LuaValue.valueOf(javaValue.toString());
|
||||
} else if ( javaValue == null ) {
|
||||
return LuaValue.NIL;
|
||||
} else {
|
||||
return LuaValue.userdataOf(javaValue);
|
||||
}
|
||||
}
|
||||
public boolean containsKey(Object key) {
|
||||
return ! env.get(toLua(key)).isnil();
|
||||
}
|
||||
public Object get(Object key) {
|
||||
return toJava(env.get(toLua(key)));
|
||||
}
|
||||
public Object put(String name, Object value) {
|
||||
LuaValue key = toLua(name);
|
||||
Object result = toJava(env.get(key));
|
||||
env.set(key, toLua(value));
|
||||
return result;
|
||||
}
|
||||
public void putAll(Map<? extends String, ? extends Object> toMerge) {
|
||||
for ( Iterator it=toMerge.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<String, Object> e = (Map.Entry<String, Object>) it.next();
|
||||
put( e.getKey(), e.getValue() );
|
||||
}
|
||||
}
|
||||
public Object remove(Object javakey) {
|
||||
LuaValue key = toLua(javakey);
|
||||
Object result = toJava(env.get(key));
|
||||
env.set(key, LuaValue.NIL);
|
||||
return result;
|
||||
}
|
||||
public boolean containsValue(Object value) {
|
||||
throw new java.lang.UnsupportedOperationException(
|
||||
"containsValue() not supported for LuaBindings");
|
||||
}
|
||||
public Set<java.util.Map.Entry<String, Object>> entrySet() {
|
||||
throw new java.lang.UnsupportedOperationException(
|
||||
"entrySet() not supported for LuaBindings");
|
||||
}
|
||||
public boolean isEmpty() {
|
||||
throw new java.lang.UnsupportedOperationException(
|
||||
"isEmpty() not supported for LuaBindings");
|
||||
}
|
||||
public Set<String> keySet() {
|
||||
throw new java.lang.UnsupportedOperationException(
|
||||
"keySet() not supported for LuaBindings");
|
||||
}
|
||||
public int size() {
|
||||
throw new java.lang.UnsupportedOperationException(
|
||||
"size() not supported for LuaBindings");
|
||||
}
|
||||
public Collection<Object> values() {
|
||||
throw new java.lang.UnsupportedOperationException(
|
||||
"values() not supported for LuaBindings");
|
||||
}
|
||||
}
|
||||
|
||||
// ------ convert char stream to byte stream for lua compiler -----
|
||||
|
||||
private final class Utf8Encoder extends InputStream {
|
||||
private final Reader r;
|
||||
private final int[] buf = new int[2];
|
||||
private int n;
|
||||
|
||||
private Utf8Encoder(Reader r) {
|
||||
this.r = r;
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
if ( n > 0 )
|
||||
return buf[--n];
|
||||
int c = r.read();
|
||||
if ( c < 0x80 )
|
||||
return c;
|
||||
n = 0;
|
||||
if ( c < 0x800 ) {
|
||||
buf[n++] = (0x80 | ( c & 0x3f));
|
||||
return (0xC0 | ((c>>6) & 0x1f));
|
||||
} else {
|
||||
buf[n++] = (0x80 | ( c & 0x3f));
|
||||
buf[n++] = (0x80 | ((c>>6) & 0x3f));
|
||||
return (0xE0 | ((c>>12) & 0x0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
127
src/jse/org/luaj/vm2/script/LuaScriptEngineFactory.java
Normal file
127
src/jse/org/luaj/vm2/script/LuaScriptEngineFactory.java
Normal file
@@ -0,0 +1,127 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2008 LuaJ. 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.script;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jim_roseborough
|
||||
*/
|
||||
public class LuaScriptEngineFactory implements ScriptEngineFactory {
|
||||
|
||||
private static final String FILEEXT = ".lua";
|
||||
|
||||
private static final String [] MIMETYPES = {
|
||||
"text/plain",
|
||||
"text/lua",
|
||||
"application/lua"
|
||||
};
|
||||
|
||||
private static final String [] NAMES = {
|
||||
"lua",
|
||||
"luaj",
|
||||
};
|
||||
|
||||
private ScriptEngine myScriptEngine;
|
||||
private List<String> extensions;
|
||||
private List<String> mimeTypes;
|
||||
private List<String> names;
|
||||
|
||||
public LuaScriptEngineFactory() {
|
||||
myScriptEngine = new LuaScriptEngine();
|
||||
extensions = Collections.nCopies(1, FILEEXT);
|
||||
mimeTypes = Arrays.asList(MIMETYPES);
|
||||
names = Arrays.asList(NAMES);
|
||||
}
|
||||
|
||||
public String getEngineName() {
|
||||
return getScriptEngine().get(ScriptEngine.ENGINE).toString();
|
||||
}
|
||||
|
||||
public String getEngineVersion() {
|
||||
return getScriptEngine().get(ScriptEngine.ENGINE_VERSION).toString();
|
||||
}
|
||||
|
||||
public List<String> getExtensions() {
|
||||
return extensions;
|
||||
}
|
||||
|
||||
public List<String> getMimeTypes() {
|
||||
return mimeTypes;
|
||||
}
|
||||
|
||||
public List<String> getNames() {
|
||||
return names;
|
||||
}
|
||||
|
||||
public String getLanguageName() {
|
||||
return getScriptEngine().get(ScriptEngine.LANGUAGE).toString();
|
||||
}
|
||||
|
||||
public String getLanguageVersion() {
|
||||
return getScriptEngine().get(ScriptEngine.LANGUAGE_VERSION).toString();
|
||||
}
|
||||
|
||||
public Object getParameter(String key) {
|
||||
return getScriptEngine().get(key).toString();
|
||||
}
|
||||
|
||||
public String getMethodCallSyntax(String obj, String m, String... args) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(obj + ":" + m + "(");
|
||||
int len = args.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(',');
|
||||
}
|
||||
sb.append(args[i]);
|
||||
}
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getOutputStatement(String toDisplay) {
|
||||
return "print(" + toDisplay + ")";
|
||||
}
|
||||
|
||||
public String getProgram(String ... statements) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int len = statements.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (i > 0) {
|
||||
sb.append('\n');
|
||||
}
|
||||
sb.append(statements[i]);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public ScriptEngine getScriptEngine() {
|
||||
return myScriptEngine;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user