Bump Cobalt version

- Remove stub for table.pack/table.unpack.
 - Remove Lua 5.3 bitlib stub. We're not on 5.3, there's no
   point emulating it.
 - Change peripheral.call to correctly adjust the error level. This is a
   terrible hack, but I believe the only good option.

It'd be good to remove load as well, but it's a little more complex due
to our injecting of _ENV.

Closes #363
This commit is contained in:
SquidDev 2020-04-16 10:48:26 +01:00
parent ef4b0a5632
commit cb8135a0d1
10 changed files with 119 additions and 81 deletions

View File

@ -22,7 +22,7 @@ ## Developing
### Code linters
CC: Tweaked uses a couple of "linters" on its source code, to enforce a consistent style across the project. While these
are run whenever you submit a PR, it's often useful to
are run whenever you submit a PR, it's often useful to run this before committing.
- **[Checkstyle]:** Checks Java code to ensure it is consistently formatted. This can be run with `./gradlew build` or
`./gradle check`.

View File

@ -77,7 +77,7 @@
runtime "mezz.jei:jei_1.12.2:4.15.0.269"
shade 'org.squiddev:Cobalt:0.5.0-SNAPSHOT'
shade 'org.squiddev:Cobalt:0.5.1-SNAPSHOT'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.2'

View File

@ -0,0 +1,35 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.core.apis;
import dan200.computercraft.api.lua.LuaException;
import javax.annotation.Nullable;
/**
* A Lua exception which does not contain its stack trace.
*/
public class FastLuaException extends LuaException
{
private static final long serialVersionUID = 5957864899303561143L;
public FastLuaException( @Nullable String message )
{
super( message );
}
public FastLuaException( @Nullable String message, int level )
{
super( message, level );
}
@Override
public synchronized Throwable fillInStackTrace()
{
return this;
}
}

View File

@ -383,22 +383,30 @@ public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull O
String methodName = getString( args, 1 );
Object[] methodArgs = Arrays.copyOfRange( args, 2, args.length );
if( side != null )
if( side == null ) throw new LuaException( "No peripheral attached" );
PeripheralWrapper p;
synchronized( m_peripherals )
{
PeripheralWrapper p;
synchronized( m_peripherals )
{
p = m_peripherals[side.ordinal()];
}
if( p != null )
{
return p.call( context, methodName, methodArgs );
}
p = m_peripherals[side.ordinal()];
}
if( p == null ) throw new LuaException( "No peripheral attached" );
try
{
return p.call( context, methodName, methodArgs );
}
catch( LuaException e )
{
// We increase the error level by one in order to shift the error level to where peripheral.call was
// invoked. It would be possible to do it in Lua code, but would add significantly more overhead.
if( e.getLevel() > 0 ) throw new FastLuaException( e.getMessage(), e.getLevel() + 1 );
throw e;
}
throw new LuaException( "No peripheral attached" );
}
default:
return null;
}
}
}

View File

@ -92,6 +92,7 @@ public CobaltLuaMachine( Computer computer, TimeoutState timeout )
m_globals.load( state, new MathLib() );
m_globals.load( state, new CoroutineLib() );
m_globals.load( state, new Bit32Lib() );
m_globals.load( state, new Utf8Lib() );
if( ComputerCraft.debug_enable ) m_globals.load( state, new DebugLib() );
// Remove globals we don't want to expose

View File

@ -70,8 +70,6 @@ if _VERSION == "Lua 5.1" then
error( p1, 2 )
end
end
table.unpack = unpack
table.pack = function( ... ) return { n = select( "#", ... ), ... } end
if _CC_DISABLE_LUA51_FEATURES then
-- Remove the Lua 5.1 features that will be removed when we update to Lua 5.2, for compatibility testing.
@ -98,70 +96,6 @@ if _VERSION == "Lua 5.1" then
end
end
if _VERSION == "Lua 5.3" and not bit32 then
-- If we're on Lua 5.3, install the bit32 api from Lua 5.2
-- (Loaded from a string so this file will still parse on <5.3 lua)
load( [[
bit32 = {}
function bit32.arshift( n, bits )
if type(n) ~= "number" or type(bits) ~= "number" then
error( "Expected number, number", 2 )
end
return n >> bits
end
function bit32.band( m, n )
if type(m) ~= "number" or type(n) ~= "number" then
error( "Expected number, number", 2 )
end
return m & n
end
function bit32.bnot( n )
if type(n) ~= "number" then
error( "Expected number", 2 )
end
return ~n
end
function bit32.bor( m, n )
if type(m) ~= "number" or type(n) ~= "number" then
error( "Expected number, number", 2 )
end
return m | n
end
function bit32.btest( m, n )
if type(m) ~= "number" or type(n) ~= "number" then
error( "Expected number, number", 2 )
end
return (m & n) ~= 0
end
function bit32.bxor( m, n )
if type(m) ~= "number" or type(n) ~= "number" then
error( "Expected number, number", 2 )
end
return m ~ n
end
function bit32.lshift( n, bits )
if type(n) ~= "number" or type(bits) ~= "number" then
error( "Expected number, number", 2 )
end
return n << bits
end
function bit32.rshift( n, bits )
if type(n) ~= "number" or type(bits) ~= "number" then
error( "Expected number, number", 2 )
end
return n >> bits
end
]] )()
end
-- Install lua parts of the os api
function os.version()
return "CraftOS 1.8"

View File

@ -10,12 +10,18 @@
import dan200.computercraft.api.lua.ILuaAPI;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.computer.BasicEnvironment;
import dan200.computercraft.core.computer.Computer;
import dan200.computercraft.core.computer.ComputerSide;
import dan200.computercraft.core.computer.MainThread;
import dan200.computercraft.core.filesystem.FileMount;
import dan200.computercraft.core.filesystem.FileSystemException;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.shared.peripheral.modem.ModemState;
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeripheral;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.jupiter.api.*;
@ -94,6 +100,7 @@ public void before() throws IOException
}
computer = new Computer( new BasicEnvironment( mount ), term, 0 );
computer.getEnvironment().setPeripheral( ComputerSide.TOP, new FakeModem() );
computer.addApi( new ILuaAPI()
{
@Override
@ -417,4 +424,33 @@ private static String formatName( String name )
{
return name.replace( "\0", " -> " );
}
private static class FakeModem extends WirelessModemPeripheral
{
FakeModem()
{
super( new ModemState(), true );
}
@Nonnull
@Override
@SuppressWarnings( "ConstantConditions" )
public World getWorld()
{
return null;
}
@Nonnull
@Override
public Vec3d getPosition()
{
return Vec3d.ZERO;
}
@Override
public boolean equals( @Nullable IPeripheral other )
{
return this == other;
}
}
}

View File

@ -224,7 +224,7 @@ expect_mt.ne = expect_mt.not_equals
function expect_mt:type(exp_type)
local actual_type = type(self.value)
if exp_type ~= actual_type then
fail(("Expected value of type %s\n got %s"):format(exp_type, actual_type))
fail(("Expected value of type %s\nbut got %s"):format(exp_type, actual_type))
end
return self
@ -273,7 +273,7 @@ end
-- @throws If they are not equivalent
function expect_mt:same(value)
if not matches({}, true, self.value, value) then
fail(("Expected %s\n but got %s"):format(format(value), format(self.value)))
fail(("Expected %s\nbut got %s"):format(format(value), format(self.value)))
end
return self
@ -356,6 +356,22 @@ function expect_mt:called_with_matching(...)
return called_with_check(matches, self, ...)
end
--- Assert that this expectation matches a Lua pattern
--
-- @tparam string pattern The pattern to match against
-- @throws If it does not match this pattern.
function expect_mt:str_match(pattern)
local actual_type = type(self.value)
if actual_type ~= "string" then
fail(("Expected value of type string\nbut got %s"):format(actual_type))
end
if not self.value:find(pattern) then
fail(("Expected %q\n to match pattern %q"):format(self.value, pattern))
end
return self
end
local expect = {}
setmetatable(expect, expect)

View File

@ -1,4 +1,6 @@
describe("The peripheral library", function()
local it_modem = peripheral.getType("top") == "modem" and it or pending
describe("peripheral.isPresent", function()
it("validates arguments", function()
peripheral.isPresent("")
@ -26,6 +28,11 @@ describe("The peripheral library", function()
expect.error(peripheral.call, nil):eq("bad argument #1 (expected string, got nil)")
expect.error(peripheral.call, "", nil):eq("bad argument #2 (expected string, got nil)")
end)
it_modem("has the correct error location", function()
expect.error(function() peripheral.call("top", "isOpen", false) end)
:str_match("^peripheral_spec.lua:%d+: bad argument #1 %(number expected, got boolean%)$")
end)
end)
describe("peripheral.wrap", function()

View File

@ -2,6 +2,7 @@ local capture = require "test_helpers".capture_program
describe("The peripherals program", function()
it("says when there are no peripherals", function()
stub(peripheral, 'getNames', function() return {} end)
expect(capture(stub, "peripherals"))
:matches { ok = true, output = "Attached Peripherals:\nNone\n", error = "" }
end)