mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-02-02 04:09:11 +00:00
Merge pull request #163 from SquidDev-CC/ComputerCraft/feature/cobalt
Replace LuaJ with Cobalt
This commit is contained in:
commit
540e2e25aa
12
build.gradle
12
build.gradle
@ -46,17 +46,29 @@ repositories {
|
|||||||
name = "JEI"
|
name = "JEI"
|
||||||
url = "http://dvs1.progwml6.com/files/maven"
|
url = "http://dvs1.progwml6.com/files/maven"
|
||||||
}
|
}
|
||||||
|
maven {
|
||||||
|
name = "squiddev"
|
||||||
|
url = "https://dl.bintray.com/squiddev/maven"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
shade
|
||||||
|
compile.extendsFrom shade
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
deobfProvided "mezz.jei:jei_1.12:4.7.5.86:api"
|
deobfProvided "mezz.jei:jei_1.12:4.7.5.86:api"
|
||||||
runtime "mezz.jei:jei_1.12:4.7.5.86"
|
runtime "mezz.jei:jei_1.12:4.7.5.86"
|
||||||
|
shade 'org.squiddev:Cobalt:0.3.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
manifest {
|
manifest {
|
||||||
attributes('FMLAT': 'computercraft_at.cfg')
|
attributes('FMLAT': 'computercraft_at.cfg')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
from configurations.shade.collect { it.isDirectory() ? it : zipTree(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
import org.ajoberstar.grgit.Grgit
|
import org.ajoberstar.grgit.Grgit
|
||||||
|
@ -35,12 +35,4 @@ zip -r $OUTPUTJAR api/src/dan200/computercraft > /dev/null
|
|||||||
cd ..
|
cd ..
|
||||||
rm -rf deploy/api
|
rm -rf deploy/api
|
||||||
|
|
||||||
echo "Adding LuaJ to deployment..."
|
|
||||||
mkdir deploy/luaj
|
|
||||||
cd deploy/luaj
|
|
||||||
jar xf ../../libs/luaj-jse-2.0.3.jar
|
|
||||||
zip -r ../$OUTPUTJAR org > /dev/null
|
|
||||||
cd ../..
|
|
||||||
rm -rf deploy/luaj
|
|
||||||
|
|
||||||
echo "Done."
|
echo "Done."
|
||||||
|
@ -15,7 +15,7 @@ import dan200.computercraft.core.apis.*;
|
|||||||
import dan200.computercraft.core.filesystem.FileSystem;
|
import dan200.computercraft.core.filesystem.FileSystem;
|
||||||
import dan200.computercraft.core.filesystem.FileSystemException;
|
import dan200.computercraft.core.filesystem.FileSystemException;
|
||||||
import dan200.computercraft.core.lua.ILuaMachine;
|
import dan200.computercraft.core.lua.ILuaMachine;
|
||||||
import dan200.computercraft.core.lua.LuaJLuaMachine;
|
import dan200.computercraft.core.lua.CobaltLuaMachine;
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -621,7 +621,7 @@ public class Computer
|
|||||||
private void initLua()
|
private void initLua()
|
||||||
{
|
{
|
||||||
// Create the lua machine
|
// Create the lua machine
|
||||||
ILuaMachine machine = new LuaJLuaMachine( this );
|
ILuaMachine machine = new CobaltLuaMachine( this );
|
||||||
|
|
||||||
// Add the APIs
|
// Add the APIs
|
||||||
for(ILuaAPI api : m_apis)
|
for(ILuaAPI api : m_apis)
|
||||||
|
@ -16,106 +16,130 @@ import dan200.computercraft.core.computer.Computer;
|
|||||||
import dan200.computercraft.core.computer.ITask;
|
import dan200.computercraft.core.computer.ITask;
|
||||||
import dan200.computercraft.core.computer.MainThread;
|
import dan200.computercraft.core.computer.MainThread;
|
||||||
|
|
||||||
import org.luaj.vm2.*;
|
import org.squiddev.cobalt.*;
|
||||||
import org.luaj.vm2.lib.Bit32Lib;
|
import org.squiddev.cobalt.compiler.CompileException;
|
||||||
import org.luaj.vm2.lib.OneArgFunction;
|
import org.squiddev.cobalt.compiler.LoadState;
|
||||||
import org.luaj.vm2.lib.VarArgFunction;
|
import org.squiddev.cobalt.debug.DebugFrame;
|
||||||
import org.luaj.vm2.lib.ZeroArgFunction;
|
import org.squiddev.cobalt.debug.DebugHandler;
|
||||||
import org.luaj.vm2.lib.jse.JsePlatform;
|
import org.squiddev.cobalt.debug.DebugState;
|
||||||
|
import org.squiddev.cobalt.function.LibFunction;
|
||||||
|
import org.squiddev.cobalt.function.LuaFunction;
|
||||||
|
import org.squiddev.cobalt.function.VarArgFunction;
|
||||||
|
import org.squiddev.cobalt.lib.*;
|
||||||
|
import org.squiddev.cobalt.lib.platform.AbstractResourceManipulator;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.io.*;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class LuaJLuaMachine implements ILuaMachine
|
import static org.squiddev.cobalt.Constants.NONE;
|
||||||
|
import static org.squiddev.cobalt.ValueFactory.valueOf;
|
||||||
|
import static org.squiddev.cobalt.ValueFactory.varargsOf;
|
||||||
|
|
||||||
|
public class CobaltLuaMachine implements ILuaMachine
|
||||||
{
|
{
|
||||||
private Computer m_computer;
|
private final Computer m_computer;
|
||||||
|
|
||||||
private LuaValue m_globals;
|
private final LuaState m_state;
|
||||||
private LuaValue m_loadString;
|
private final LuaTable m_globals;
|
||||||
private LuaValue m_assert;
|
|
||||||
private LuaValue m_coroutine_create;
|
|
||||||
private LuaValue m_coroutine_resume;
|
|
||||||
private LuaValue m_coroutine_yield;
|
|
||||||
|
|
||||||
private LuaValue m_mainRoutine;
|
private LuaThread m_mainRoutine;
|
||||||
private String m_eventFilter;
|
private String m_eventFilter;
|
||||||
private String m_softAbortMessage;
|
private String m_softAbortMessage;
|
||||||
private String m_hardAbortMessage;
|
private String m_hardAbortMessage;
|
||||||
|
|
||||||
private Map<Object, LuaValue> m_valuesInProgress;
|
public CobaltLuaMachine( Computer computer )
|
||||||
private Map<LuaValue, Object> m_objectsInProgress;
|
|
||||||
|
|
||||||
public LuaJLuaMachine( Computer computer )
|
|
||||||
{
|
{
|
||||||
m_computer = computer;
|
m_computer = computer;
|
||||||
|
|
||||||
// Create an environment to run in
|
// Create an environment to run in
|
||||||
m_globals = JsePlatform.debugGlobals();
|
final LuaState state = this.m_state = new LuaState( new AbstractResourceManipulator()
|
||||||
m_globals.load( new Bit32Lib() );
|
|
||||||
m_loadString = m_globals.get("loadstring");
|
|
||||||
m_assert = m_globals.get("assert");
|
|
||||||
|
|
||||||
LuaValue coroutine = m_globals.get("coroutine");
|
|
||||||
final LuaValue native_coroutine_create = coroutine.get("create");
|
|
||||||
|
|
||||||
LuaValue debug = m_globals.get("debug");
|
|
||||||
final LuaValue debug_sethook = debug.get("sethook");
|
|
||||||
|
|
||||||
coroutine.set("create", new OneArgFunction() {
|
|
||||||
@Override
|
|
||||||
public LuaValue call( LuaValue value )
|
|
||||||
{
|
{
|
||||||
final LuaThread thread = native_coroutine_create.call( value ).checkthread();
|
|
||||||
debug_sethook.invoke( new LuaValue[] {
|
|
||||||
thread,
|
|
||||||
new ZeroArgFunction() {
|
|
||||||
@Override
|
@Override
|
||||||
public LuaValue call() {
|
public InputStream findResource( String filename )
|
||||||
String hardAbortMessage = m_hardAbortMessage;
|
|
||||||
if( hardAbortMessage != null )
|
|
||||||
{
|
{
|
||||||
LuaThread.yield(LuaValue.NIL);
|
return null;
|
||||||
}
|
}
|
||||||
return LuaValue.NIL;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
LuaValue.NIL,
|
|
||||||
LuaValue.valueOf(100000)
|
|
||||||
} );
|
} );
|
||||||
return thread;
|
state.debug = new DebugHandler( state )
|
||||||
}
|
{
|
||||||
});
|
private int count = 0;
|
||||||
|
private boolean hasSoftAbort;
|
||||||
|
|
||||||
m_coroutine_create = coroutine.get("create");
|
@Override
|
||||||
m_coroutine_resume = coroutine.get("resume");
|
public void onInstruction( DebugState ds, DebugFrame di, int pc, Varargs extras, int top ) throws LuaError
|
||||||
m_coroutine_yield = coroutine.get("yield");
|
{
|
||||||
|
int count = ++this.count;
|
||||||
|
if( count > 100000 )
|
||||||
|
{
|
||||||
|
if( m_hardAbortMessage != null ) LuaThread.yield( state, NONE );
|
||||||
|
this.count = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handleSoftAbort();
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onInstruction( ds, di, pc, extras, top );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void poll() throws LuaError
|
||||||
|
{
|
||||||
|
if( m_hardAbortMessage != null ) LuaThread.yield( state, NONE );
|
||||||
|
handleSoftAbort();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSoftAbort() throws LuaError {
|
||||||
|
// If the soft abort has been cleared then we can reset our flags and continue.
|
||||||
|
String message = m_softAbortMessage;
|
||||||
|
if (message == null) {
|
||||||
|
hasSoftAbort = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasSoftAbort && m_hardAbortMessage == null) {
|
||||||
|
// If we have fired our soft abort, but we haven't been hard aborted then everything is OK.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasSoftAbort = true;
|
||||||
|
throw new LuaError(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
m_globals = new LuaTable();
|
||||||
|
state.setupThread( m_globals );
|
||||||
|
|
||||||
|
// Add basic libraries
|
||||||
|
m_globals.load( state, new BaseLib() );
|
||||||
|
m_globals.load( state, new TableLib() );
|
||||||
|
m_globals.load( state, new StringLib() );
|
||||||
|
m_globals.load( state, new MathLib() );
|
||||||
|
m_globals.load( state, new CoroutineLib() );
|
||||||
|
m_globals.load( state, new Bit32Lib() );
|
||||||
|
|
||||||
|
// Register custom load/loadstring provider which automatically adds prefixes.
|
||||||
|
LibFunction.bind( state, m_globals, PrefixLoader.class, new String[]{ "load", "loadstring" } );
|
||||||
|
|
||||||
// Remove globals we don't want to expose
|
// Remove globals we don't want to expose
|
||||||
m_globals.set( "collectgarbage", LuaValue.NIL );
|
m_globals.rawset( "collectgarbage", Constants.NIL );
|
||||||
m_globals.set( "dofile", LuaValue.NIL );
|
m_globals.rawset( "dofile", Constants.NIL );
|
||||||
m_globals.set( "loadfile", LuaValue.NIL );
|
m_globals.rawset( "loadfile", Constants.NIL );
|
||||||
m_globals.set( "module", LuaValue.NIL );
|
m_globals.rawset( "print", Constants.NIL );
|
||||||
m_globals.set( "require", LuaValue.NIL );
|
|
||||||
m_globals.set( "package", LuaValue.NIL );
|
|
||||||
m_globals.set( "io", LuaValue.NIL );
|
|
||||||
m_globals.set( "os", LuaValue.NIL );
|
|
||||||
m_globals.set( "print", LuaValue.NIL );
|
|
||||||
m_globals.set( "luajava", LuaValue.NIL );
|
|
||||||
m_globals.set( "debug", LuaValue.NIL );
|
|
||||||
m_globals.set( "newproxy", LuaValue.NIL );
|
|
||||||
m_globals.set( "__inext", LuaValue.NIL );
|
|
||||||
|
|
||||||
// Add version globals
|
// Add version globals
|
||||||
m_globals.set( "_VERSION", "Lua 5.1" );
|
m_globals.rawset( "_VERSION", valueOf( "Lua 5.1" ) );
|
||||||
m_globals.set( "_HOST", computer.getAPIEnvironment().getComputerEnvironment().getHostString() );
|
m_globals.rawset( "_HOST", valueOf( computer.getAPIEnvironment().getComputerEnvironment().getHostString() ) );
|
||||||
m_globals.set( "_CC_DEFAULT_SETTINGS", toValue( ComputerCraft.default_computer_settings ) );
|
m_globals.rawset( "_CC_DEFAULT_SETTINGS", valueOf( ComputerCraft.default_computer_settings ) );
|
||||||
if( ComputerCraft.disable_lua51_features )
|
if( ComputerCraft.disable_lua51_features )
|
||||||
{
|
{
|
||||||
m_globals.set( "_CC_DISABLE_LUA51_FEATURES", toValue( true ) );
|
m_globals.rawset( "_CC_DISABLE_LUA51_FEATURES", Constants.TRUE );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Our main function will go here
|
// Our main function will go here
|
||||||
@ -134,7 +158,7 @@ public class LuaJLuaMachine implements ILuaMachine
|
|||||||
String[] names = api.getNames();
|
String[] names = api.getNames();
|
||||||
for( String name : names )
|
for( String name : names )
|
||||||
{
|
{
|
||||||
m_globals.set( name, table );
|
m_globals.rawset( name, table );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,48 +173,23 @@ public class LuaJLuaMachine implements ILuaMachine
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Read the whole bios into a string
|
LuaFunction value = LoadState.load( m_state, bios, "@bios.lua", m_globals );
|
||||||
String biosText;
|
m_mainRoutine = new LuaThread( m_state, value, m_globals );
|
||||||
try
|
}
|
||||||
|
catch( CompileException e )
|
||||||
{
|
{
|
||||||
InputStreamReader isr;
|
if( m_mainRoutine != null )
|
||||||
try
|
|
||||||
{
|
{
|
||||||
isr = new InputStreamReader( bios, "UTF-8" );
|
m_mainRoutine.abandon();
|
||||||
|
m_mainRoutine = null;
|
||||||
}
|
}
|
||||||
catch( UnsupportedEncodingException e )
|
|
||||||
{
|
|
||||||
isr = new InputStreamReader( bios );
|
|
||||||
}
|
|
||||||
BufferedReader reader = new BufferedReader( isr );
|
|
||||||
StringBuilder fileText = new StringBuilder( "" );
|
|
||||||
String line = reader.readLine();
|
|
||||||
while( line != null ) {
|
|
||||||
fileText.append( line );
|
|
||||||
line = reader.readLine();
|
|
||||||
if( line != null ) {
|
|
||||||
fileText.append( "\n" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
biosText = fileText.toString();
|
|
||||||
}
|
}
|
||||||
catch( IOException e )
|
catch( IOException e )
|
||||||
{
|
|
||||||
throw new LuaError( "Could not read file" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load it
|
|
||||||
LuaValue program = m_assert.call( m_loadString.call(
|
|
||||||
toValue( biosText ), toValue( "bios.lua" )
|
|
||||||
));
|
|
||||||
m_mainRoutine = m_coroutine_create.call( program );
|
|
||||||
}
|
|
||||||
catch( LuaError e )
|
|
||||||
{
|
{
|
||||||
ComputerCraft.log.warn( "Could not load bios.lua ", e );
|
ComputerCraft.log.warn( "Could not load bios.lua ", e );
|
||||||
if( m_mainRoutine != null )
|
if( m_mainRoutine != null )
|
||||||
{
|
{
|
||||||
((LuaThread)m_mainRoutine).abandon();
|
m_mainRoutine.abandon();
|
||||||
m_mainRoutine = null;
|
m_mainRoutine = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,32 +210,25 @@ public class LuaJLuaMachine implements ILuaMachine
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
LuaValue[] resumeArgs;
|
Varargs resumeArgs = Constants.NONE;
|
||||||
if( eventName != null )
|
if( eventName != null )
|
||||||
{
|
{
|
||||||
resumeArgs = toValues( arguments, 2 );
|
resumeArgs = varargsOf( valueOf( eventName ), toValues( arguments ) );
|
||||||
resumeArgs[0] = m_mainRoutine;
|
|
||||||
resumeArgs[1] = toValue( eventName );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
resumeArgs = new LuaValue[1];
|
|
||||||
resumeArgs[0] = m_mainRoutine;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Varargs results = m_coroutine_resume.invoke( LuaValue.varargsOf( resumeArgs ) );
|
Varargs results = m_mainRoutine.resume( resumeArgs );
|
||||||
if( m_hardAbortMessage != null )
|
if( m_hardAbortMessage != null )
|
||||||
{
|
{
|
||||||
throw new LuaError( m_hardAbortMessage );
|
throw new LuaError( m_hardAbortMessage );
|
||||||
}
|
}
|
||||||
else if( results.arg1().checkboolean() == false )
|
else if( !results.first().checkBoolean() )
|
||||||
{
|
{
|
||||||
throw new LuaError( results.arg(2).checkstring().toString() );
|
throw new LuaError( results.arg( 2 ).checkString() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LuaValue filter = results.arg(2);
|
LuaValue filter = results.arg( 2 );
|
||||||
if( filter.isstring() )
|
if( filter.isString() )
|
||||||
{
|
{
|
||||||
m_eventFilter = filter.toString();
|
m_eventFilter = filter.toString();
|
||||||
}
|
}
|
||||||
@ -246,15 +238,15 @@ public class LuaJLuaMachine implements ILuaMachine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaThread mainThread = (LuaThread)m_mainRoutine;
|
LuaThread mainThread = m_mainRoutine;
|
||||||
if( mainThread.getStatus().equals("dead") )
|
if( mainThread.getStatus().equals( "dead" ) )
|
||||||
{
|
{
|
||||||
m_mainRoutine = null;
|
m_mainRoutine = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch( LuaError e )
|
catch( LuaError e )
|
||||||
{
|
{
|
||||||
((LuaThread)m_mainRoutine).abandon();
|
m_mainRoutine.abandon();
|
||||||
m_mainRoutine = null;
|
m_mainRoutine = null;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@ -300,55 +292,40 @@ public class LuaJLuaMachine implements ILuaMachine
|
|||||||
{
|
{
|
||||||
if( m_mainRoutine != null )
|
if( m_mainRoutine != null )
|
||||||
{
|
{
|
||||||
LuaThread mainThread = (LuaThread)m_mainRoutine;
|
LuaThread mainThread = m_mainRoutine;
|
||||||
mainThread.abandon();
|
mainThread.abandon();
|
||||||
m_mainRoutine = null;
|
m_mainRoutine = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryAbort() throws LuaError
|
|
||||||
{
|
|
||||||
// while( m_stopped )
|
|
||||||
// {
|
|
||||||
// m_coroutine_yield.call();
|
|
||||||
// }
|
|
||||||
|
|
||||||
String abortMessage = m_softAbortMessage;
|
|
||||||
if( abortMessage != null )
|
|
||||||
{
|
|
||||||
m_softAbortMessage = null;
|
|
||||||
m_hardAbortMessage = null;
|
|
||||||
throw new LuaError( abortMessage );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private LuaTable wrapLuaObject( ILuaObject object )
|
private LuaTable wrapLuaObject( ILuaObject object )
|
||||||
{
|
{
|
||||||
LuaTable table = new LuaTable();
|
LuaTable table = new LuaTable();
|
||||||
String[] methods = object.getMethodNames();
|
String[] methods = object.getMethodNames();
|
||||||
for(int i=0; i<methods.length; ++i )
|
for( int i = 0; i < methods.length; ++i )
|
||||||
{
|
{
|
||||||
if( methods[i] != null )
|
if( methods[ i ] != null )
|
||||||
{
|
{
|
||||||
final int method = i;
|
final int method = i;
|
||||||
final ILuaObject apiObject = object;
|
final ILuaObject apiObject = object;
|
||||||
final String methodName = methods[i];
|
final String methodName = methods[ i ];
|
||||||
table.set( methodName, new VarArgFunction() {
|
table.rawset( methodName, new VarArgFunction()
|
||||||
@Override
|
{
|
||||||
public Varargs invoke( Varargs _args )
|
@Override
|
||||||
|
public Varargs invoke( final LuaState state, Varargs _args ) throws LuaError
|
||||||
{
|
{
|
||||||
tryAbort();
|
|
||||||
Object[] arguments = toObjects( _args, 1 );
|
Object[] arguments = toObjects( _args, 1 );
|
||||||
Object[] results;
|
Object[] results;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
results = apiObject.callMethod( new ILuaContext() {
|
results = apiObject.callMethod( new ILuaContext()
|
||||||
|
{
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Object[] pullEvent( String filter ) throws LuaException, InterruptedException
|
public Object[] pullEvent( String filter ) throws LuaException, InterruptedException
|
||||||
{
|
{
|
||||||
Object[] results = pullEventRaw( filter );
|
Object[] results = pullEventRaw( filter );
|
||||||
if( results.length >= 1 && results[0].equals( "terminate" ) )
|
if( results.length >= 1 && results[ 0 ].equals( "terminate" ) )
|
||||||
{
|
{
|
||||||
throw new LuaException( "Terminated", 0 );
|
throw new LuaException( "Terminated", 0 );
|
||||||
}
|
}
|
||||||
@ -368,14 +345,17 @@ public class LuaJLuaMachine implements ILuaMachine
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
LuaValue[] yieldValues = toValues( yieldArgs, 0 );
|
Varargs results = LuaThread.yield( state, toValues( yieldArgs ) );
|
||||||
Varargs results = m_coroutine_yield.invoke( LuaValue.varargsOf( yieldValues ) );
|
|
||||||
return toObjects( results, 1 );
|
return toObjects( results, 1 );
|
||||||
}
|
}
|
||||||
catch( OrphanedThread e )
|
catch( OrphanedThread e )
|
||||||
{
|
{
|
||||||
throw new InterruptedException();
|
throw new InterruptedException();
|
||||||
}
|
}
|
||||||
|
catch( Throwable e )
|
||||||
|
{
|
||||||
|
throw new RuntimeException( e );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -450,10 +430,10 @@ public class LuaJLuaMachine implements ILuaMachine
|
|||||||
Object[] response = pullEvent( "task_complete" );
|
Object[] response = pullEvent( "task_complete" );
|
||||||
if( response.length >= 3 && response[ 1 ] instanceof Number && response[ 2 ] instanceof Boolean )
|
if( response.length >= 3 && response[ 1 ] instanceof Number && response[ 2 ] instanceof Boolean )
|
||||||
{
|
{
|
||||||
if( ( (Number)response[ 1 ] ).intValue() == taskID )
|
if( ((Number) response[ 1 ]).intValue() == taskID )
|
||||||
{
|
{
|
||||||
Object[] returnValues = new Object[ response.length - 3 ];
|
Object[] returnValues = new Object[ response.length - 3 ];
|
||||||
if( (Boolean)response[ 2 ] )
|
if( (Boolean) response[ 2 ] )
|
||||||
{
|
{
|
||||||
// Extract the return values from the event and return them
|
// Extract the return values from the event and return them
|
||||||
System.arraycopy( response, 3, returnValues, 0, returnValues.length );
|
System.arraycopy( response, 3, returnValues, 0, returnValues.length );
|
||||||
@ -462,9 +442,9 @@ public class LuaJLuaMachine implements ILuaMachine
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Extract the error message from the event and raise it
|
// Extract the error message from the event and raise it
|
||||||
if( response.length >= 4 && response[3] instanceof String )
|
if( response.length >= 4 && response[ 3 ] instanceof String )
|
||||||
{
|
{
|
||||||
throw new LuaException( (String)response[ 3 ] );
|
throw new LuaException( (String) response[ 3 ] );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -494,7 +474,7 @@ public class LuaJLuaMachine implements ILuaMachine
|
|||||||
}
|
}
|
||||||
throw new LuaError( "Java Exception Thrown: " + t.toString(), 0 );
|
throw new LuaError( "Java Exception Thrown: " + t.toString(), 0 );
|
||||||
}
|
}
|
||||||
return LuaValue.varargsOf( toValues( results, 0 ) );
|
return toValues( results );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
@ -502,159 +482,145 @@ public class LuaJLuaMachine implements ILuaMachine
|
|||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LuaValue toValue( Object object )
|
private LuaValue toValue( Object object, Map<Object, LuaValue> values )
|
||||||
{
|
{
|
||||||
if( object == null )
|
if( object == null )
|
||||||
{
|
{
|
||||||
return LuaValue.NIL;
|
return Constants.NIL;
|
||||||
}
|
}
|
||||||
else if( object instanceof Number )
|
else if( object instanceof Number )
|
||||||
{
|
{
|
||||||
double d = ((Number)object).doubleValue();
|
double d = ((Number) object).doubleValue();
|
||||||
return LuaValue.valueOf( d );
|
return valueOf( d );
|
||||||
}
|
}
|
||||||
else if( object instanceof Boolean )
|
else if( object instanceof Boolean )
|
||||||
{
|
{
|
||||||
boolean b = (Boolean) object;
|
return valueOf( (Boolean) object );
|
||||||
return LuaValue.valueOf( b );
|
|
||||||
}
|
}
|
||||||
else if( object instanceof String )
|
else if( object instanceof String )
|
||||||
{
|
{
|
||||||
String s = object.toString();
|
String s = object.toString();
|
||||||
return LuaValue.valueOf( s );
|
return valueOf( s );
|
||||||
}
|
}
|
||||||
else if( object instanceof byte[] )
|
else if( object instanceof byte[] )
|
||||||
{
|
{
|
||||||
byte[] b = (byte[]) object;
|
byte[] b = (byte[]) object;
|
||||||
return LuaValue.valueOf( Arrays.copyOf( b, b.length ) );
|
return valueOf( Arrays.copyOf( b, b.length ) );
|
||||||
}
|
}
|
||||||
else if( object instanceof Map )
|
else if( object instanceof Map )
|
||||||
{
|
{
|
||||||
// Table:
|
// Table:
|
||||||
// Start remembering stuff
|
// Start remembering stuff
|
||||||
boolean clearWhenDone = false;
|
if( values == null )
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if( m_valuesInProgress == null )
|
values = new IdentityHashMap<>();
|
||||||
{
|
|
||||||
m_valuesInProgress = new IdentityHashMap<>();
|
|
||||||
clearWhenDone = true;
|
|
||||||
}
|
}
|
||||||
else if( m_valuesInProgress.containsKey( object ) )
|
else if( values.containsKey( object ) )
|
||||||
{
|
{
|
||||||
return m_valuesInProgress.get( object );
|
return values.get( object );
|
||||||
}
|
}
|
||||||
LuaValue table = new LuaTable();
|
LuaTable table = new LuaTable();
|
||||||
m_valuesInProgress.put( object, table );
|
values.put( object, table );
|
||||||
|
|
||||||
// Convert all keys
|
// Convert all keys
|
||||||
for( Map.Entry<?, ?> pair : ((Map<?, ?>) object).entrySet() )
|
for( Map.Entry<?, ?> pair : ((Map<?, ?>) object).entrySet() )
|
||||||
{
|
{
|
||||||
LuaValue key = toValue( pair.getKey() );
|
LuaValue key = toValue( pair.getKey(), values );
|
||||||
LuaValue value = toValue( pair.getValue() );
|
LuaValue value = toValue( pair.getValue(), values );
|
||||||
if( !key.isnil() && !value.isnil() )
|
if( !key.isNil() && !value.isNil() )
|
||||||
{
|
{
|
||||||
table.set( key, value );
|
table.rawset( key, value );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
// Clear (if exiting top level)
|
|
||||||
if( clearWhenDone )
|
|
||||||
{
|
|
||||||
m_valuesInProgress = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( object instanceof ILuaObject )
|
else if( object instanceof ILuaObject )
|
||||||
{
|
{
|
||||||
return wrapLuaObject( (ILuaObject)object );
|
return wrapLuaObject( (ILuaObject) object );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return LuaValue.NIL;
|
return Constants.NIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private LuaValue[] toValues( Object[] objects, int leaveEmpty )
|
private Varargs toValues( Object[] objects )
|
||||||
{
|
{
|
||||||
if( objects == null || objects.length == 0 )
|
if( objects == null || objects.length == 0 )
|
||||||
{
|
{
|
||||||
return new LuaValue[ leaveEmpty ];
|
return Constants.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaValue[] values = new LuaValue[objects.length + leaveEmpty];
|
LuaValue[] values = new LuaValue[ objects.length ];
|
||||||
for( int i=0; i<values.length; ++i )
|
for( int i = 0; i < values.length; ++i )
|
||||||
{
|
{
|
||||||
if( i < leaveEmpty )
|
Object object = objects[ i ];
|
||||||
{
|
values[ i ] = toValue( object, null );
|
||||||
values[i] = null;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
Object object = objects[i - leaveEmpty];
|
return varargsOf( values );
|
||||||
values[i] = toValue( object );
|
|
||||||
}
|
|
||||||
return values;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object toObject( LuaValue value )
|
private static Object toObject( LuaValue value, Map<LuaValue, Object> objects )
|
||||||
{
|
{
|
||||||
switch( value.type() )
|
switch( value.type() )
|
||||||
{
|
{
|
||||||
case LuaValue.TNIL:
|
case Constants.TNIL:
|
||||||
case LuaValue.TNONE:
|
case Constants.TNONE:
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
case LuaValue.TINT:
|
case Constants.TINT:
|
||||||
case LuaValue.TNUMBER:
|
case Constants.TNUMBER:
|
||||||
{
|
{
|
||||||
return value.todouble();
|
return value.toDouble();
|
||||||
}
|
}
|
||||||
case LuaValue.TBOOLEAN:
|
case Constants.TBOOLEAN:
|
||||||
{
|
{
|
||||||
return value.toboolean();
|
return value.toBoolean();
|
||||||
}
|
}
|
||||||
case LuaValue.TSTRING:
|
case Constants.TSTRING:
|
||||||
{
|
{
|
||||||
LuaString str = value.checkstring();
|
return value.toString();
|
||||||
return str.tojstring();
|
|
||||||
}
|
}
|
||||||
case LuaValue.TTABLE:
|
case Constants.TTABLE:
|
||||||
{
|
{
|
||||||
// Table:
|
// Table:
|
||||||
boolean clearWhenDone = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Start remembering stuff
|
// Start remembering stuff
|
||||||
if( m_objectsInProgress == null )
|
if( objects == null )
|
||||||
{
|
{
|
||||||
m_objectsInProgress = new IdentityHashMap<>();
|
objects = new IdentityHashMap<>();
|
||||||
clearWhenDone = true;
|
|
||||||
}
|
}
|
||||||
else if( m_objectsInProgress.containsKey( value ) )
|
else if( objects.containsKey( value ) )
|
||||||
{
|
{
|
||||||
return m_objectsInProgress.get( value );
|
return objects.get( value );
|
||||||
}
|
}
|
||||||
Map<Object, Object> table = new HashMap<>();
|
Map<Object, Object> table = new HashMap<>();
|
||||||
m_objectsInProgress.put( value, table );
|
objects.put( value, table );
|
||||||
|
|
||||||
|
LuaTable luaTable = (LuaTable) value;
|
||||||
|
|
||||||
// Convert all keys
|
// Convert all keys
|
||||||
LuaValue k = LuaValue.NIL;
|
LuaValue k = Constants.NIL;
|
||||||
while( true )
|
while( true )
|
||||||
{
|
{
|
||||||
Varargs keyValue = value.next( k );
|
Varargs keyValue;
|
||||||
k = keyValue.arg1();
|
try
|
||||||
if( k.isnil() )
|
{
|
||||||
|
keyValue = luaTable.next( k );
|
||||||
|
}
|
||||||
|
catch( LuaError luaError )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
k = keyValue.first();
|
||||||
|
if( k.isNil() )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaValue v = keyValue.arg(2);
|
LuaValue v = keyValue.arg( 2 );
|
||||||
Object keyObject = toObject(k);
|
Object keyObject = toObject( k, objects );
|
||||||
Object valueObject = toObject(v);
|
Object valueObject = toObject( v, objects );
|
||||||
if( keyObject != null && valueObject != null )
|
if( keyObject != null && valueObject != null )
|
||||||
{
|
{
|
||||||
table.put( keyObject, valueObject );
|
table.put( keyObject, valueObject );
|
||||||
@ -662,15 +628,6 @@ public class LuaJLuaMachine implements ILuaMachine
|
|||||||
}
|
}
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
// Clear (if exiting top level)
|
|
||||||
if( clearWhenDone )
|
|
||||||
{
|
|
||||||
m_objectsInProgress = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@ -678,16 +635,104 @@ public class LuaJLuaMachine implements ILuaMachine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object[] toObjects( Varargs values, int startIdx )
|
private static Object[] toObjects( Varargs values, int startIdx )
|
||||||
{
|
{
|
||||||
int count = values.narg();
|
int count = values.count();
|
||||||
Object[] objects = new Object[ count - startIdx + 1 ];
|
Object[] objects = new Object[ count - startIdx + 1 ];
|
||||||
for( int n=startIdx; n<=count; ++n )
|
for( int n = startIdx; n <= count; ++n )
|
||||||
{
|
{
|
||||||
int i = n - startIdx;
|
int i = n - startIdx;
|
||||||
LuaValue value = values.arg(n);
|
LuaValue value = values.arg( n );
|
||||||
objects[i] = toObject( value );
|
objects[ i ] = toObject( value, null );
|
||||||
}
|
}
|
||||||
return objects;
|
return objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class PrefixLoader extends VarArgFunction
|
||||||
|
{
|
||||||
|
private static final LuaString FUNCTION_STR = valueOf( "function" );
|
||||||
|
private static final LuaString EQ_STR = valueOf( "=" );
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Varargs invoke( LuaState state, Varargs args ) throws LuaError
|
||||||
|
{
|
||||||
|
switch (opcode)
|
||||||
|
{
|
||||||
|
case 0: // "load", // ( func [,chunkname] ) -> chunk | nil, msg
|
||||||
|
{
|
||||||
|
LuaValue func = args.arg( 1 ).checkFunction();
|
||||||
|
LuaString chunkname = args.arg( 2 ).optLuaString( FUNCTION_STR );
|
||||||
|
if( !chunkname.startsWith( '@' ) && !chunkname.startsWith( '=' ) )
|
||||||
|
{
|
||||||
|
chunkname = OperationHelper.concat( EQ_STR, chunkname );
|
||||||
|
}
|
||||||
|
return BaseLib.loadStream( state, new StringInputStream( state, func ), chunkname );
|
||||||
|
}
|
||||||
|
case 1: // "loadstring", // ( string [,chunkname] ) -> chunk | nil, msg
|
||||||
|
{
|
||||||
|
LuaString script = args.arg( 1 ).checkLuaString();
|
||||||
|
LuaString chunkname = args.arg( 2 ).optLuaString( script );
|
||||||
|
if( !chunkname.startsWith( '@' ) && !chunkname.startsWith( '=' ) )
|
||||||
|
{
|
||||||
|
chunkname = OperationHelper.concat( EQ_STR, chunkname );
|
||||||
|
}
|
||||||
|
return BaseLib.loadStream( state, script.toInputStream(), chunkname );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class StringInputStream extends InputStream
|
||||||
|
{
|
||||||
|
private final LuaState state;
|
||||||
|
private final LuaValue func;
|
||||||
|
private byte[] bytes;
|
||||||
|
private int offset, remaining = 0;
|
||||||
|
|
||||||
|
public StringInputStream( LuaState state, LuaValue func )
|
||||||
|
{
|
||||||
|
this.state = state;
|
||||||
|
this.func = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException
|
||||||
|
{
|
||||||
|
if( remaining <= 0 )
|
||||||
|
{
|
||||||
|
LuaValue s;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
s = OperationHelper.call( state, func );
|
||||||
|
} catch (LuaError e)
|
||||||
|
{
|
||||||
|
throw new IOException( e );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( s.isNil() )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
LuaString ls;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ls = s.strvalue();
|
||||||
|
} catch (LuaError e)
|
||||||
|
{
|
||||||
|
throw new IOException( e );
|
||||||
|
}
|
||||||
|
bytes = ls.bytes;
|
||||||
|
offset = ls.offset;
|
||||||
|
remaining = ls.length;
|
||||||
|
if( remaining <= 0 )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--remaining;
|
||||||
|
return bytes[offset++];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -142,39 +142,6 @@ if _VERSION == "Lua 5.3" and not bit32 then
|
|||||||
]] )()
|
]] )()
|
||||||
end
|
end
|
||||||
|
|
||||||
if string.find( _HOST, "ComputerCraft" ) == 1 then
|
|
||||||
-- Prevent access to metatables or environments of strings, as these are global between all computers
|
|
||||||
local nativegetmetatable = getmetatable
|
|
||||||
local nativeerror = error
|
|
||||||
local nativetype = type
|
|
||||||
local string_metatable = nativegetmetatable("")
|
|
||||||
function getmetatable( t )
|
|
||||||
local mt = nativegetmetatable( t )
|
|
||||||
if mt == string_metatable then
|
|
||||||
nativeerror( "Attempt to access string metatable", 2 )
|
|
||||||
else
|
|
||||||
return mt
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if _VERSION == "Lua 5.1" and not _CC_DISABLE_LUA51_FEATURES then
|
|
||||||
local string_env = nativegetfenv(("").gsub)
|
|
||||||
function getfenv( env )
|
|
||||||
if env == nil then
|
|
||||||
env = 2
|
|
||||||
elseif nativetype( env ) == "number" and env > 0 then
|
|
||||||
env = env + 1
|
|
||||||
end
|
|
||||||
local fenv = nativegetfenv(env)
|
|
||||||
if fenv == string_env then
|
|
||||||
--nativeerror( "Attempt to access string metatable", 2 )
|
|
||||||
return nativegetfenv( 0 )
|
|
||||||
else
|
|
||||||
return fenv
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Install lua parts of the os api
|
-- Install lua parts of the os api
|
||||||
function os.version()
|
function os.version()
|
||||||
return "CraftOS 1.8"
|
return "CraftOS 1.8"
|
||||||
@ -572,7 +539,7 @@ loadfile = function( _sFile, _tEnv )
|
|||||||
end
|
end
|
||||||
local file = fs.open( _sFile, "r" )
|
local file = fs.open( _sFile, "r" )
|
||||||
if file then
|
if file then
|
||||||
local func, err = load( file.readAll(), fs.getName( _sFile ), "t", _tEnv )
|
local func, err = load( file.readAll(), "@" .. fs.getName( _sFile ), "t", _tEnv )
|
||||||
file.close()
|
file.close()
|
||||||
return func, err
|
return func, err
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user