mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-11-03 23:22:59 +00:00 
			
		
		
		
	Compare commits
	
		
			5 Commits
		
	
	
		
			v1.20.4-1.
			...
			v1.20.1-1.
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					a0f759527d | ||
| 
						 | 
					385e4210fa | ||
| 
						 | 
					d2896473f2 | ||
| 
						 | 
					f14cb2a3d1 | ||
| 
						 | 
					8db5c6bc3a | 
@@ -10,7 +10,7 @@ kotlin.jvm.target.validation.mode=error
 | 
			
		||||
 | 
			
		||||
# Mod properties
 | 
			
		||||
isUnstable=false
 | 
			
		||||
modVersion=1.109.5
 | 
			
		||||
modVersion=1.109.6
 | 
			
		||||
 | 
			
		||||
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
 | 
			
		||||
mcVersion=1.20.1
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ slf4j = "2.0.1"
 | 
			
		||||
asm = "9.6"
 | 
			
		||||
autoService = "1.1.1"
 | 
			
		||||
checkerFramework = "3.42.0"
 | 
			
		||||
cobalt = "0.9.0"
 | 
			
		||||
cobalt = "0.9.1"
 | 
			
		||||
commonsCli = "1.6.0"
 | 
			
		||||
jetbrainsAnnotations = "24.1.0"
 | 
			
		||||
jsr305 = "3.0.2"
 | 
			
		||||
 
 | 
			
		||||
@@ -105,6 +105,10 @@
 | 
			
		||||
   /projects/core/src/main/resources/data/computercraft/lua/rom/apis/turtle/turtle.lua)
 | 
			
		||||
  (linters -var:deprecated))
 | 
			
		||||
 | 
			
		||||
;; Suppress unused variable warnings in the parser.
 | 
			
		||||
(at /projects/core/src/main/resources/data/computercraft/lua/rom/modules/main/cc/internal/syntax/parser.lua
 | 
			
		||||
  (linters -var:unused))
 | 
			
		||||
 | 
			
		||||
(at /projects/core/src/test/resources/test-rom
 | 
			
		||||
  ; We should still be able to test deprecated members.
 | 
			
		||||
  (linters -var:deprecated)
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,8 @@
 | 
			
		||||
 | 
			
		||||
package dan200.computercraft.api.lua;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents a Lua object which is stored as a global variable on computer startup. This must either provide
 | 
			
		||||
 * {@link LuaFunction} annotated functions or implement {@link IDynamicLuaObject}.
 | 
			
		||||
@@ -15,12 +17,31 @@ package dan200.computercraft.api.lua;
 | 
			
		||||
 */
 | 
			
		||||
public interface ILuaAPI {
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the globals this API will be assigned to. This will override any other global, so you should
 | 
			
		||||
     * Get the globals this API will be assigned to.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * This will override any other global, so you should be careful to pick a unique name. Alternatively, you may
 | 
			
		||||
     * return the empty array here, and instead override {@link #getModuleName()}.
 | 
			
		||||
     *
 | 
			
		||||
     * @return A list of globals this API will be assigned to.
 | 
			
		||||
     */
 | 
			
		||||
    String[] getNames();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the module name this API should be available as.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Rather than (or as well as) making this API available as a global, APIs can be exposed as {@code require}able
 | 
			
		||||
     * modules. This is generally more idiomatic, as it avoids polluting the global environment.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Modules defined here take precedence over user-defined modules, and so like with {@link #getNames()}, you should
 | 
			
		||||
     * be careful to pick a unique name. It is recommended that module names should be camel case, and live under a
 | 
			
		||||
     * namespace associated with your mod. For instance, {@code "mod_id.a_custom_api"}.
 | 
			
		||||
     *
 | 
			
		||||
     * @return The module name of this API, or {@code null} if this API should not be loadable as a module.
 | 
			
		||||
     */
 | 
			
		||||
    default @Nullable String getModuleName() {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when the computer is turned on.
 | 
			
		||||
     * <p>
 | 
			
		||||
 
 | 
			
		||||
@@ -275,9 +275,9 @@ public final class MemoryMount extends AbstractInMemoryMount<MemoryMount.FileEnt
 | 
			
		||||
            checkClosed();
 | 
			
		||||
 | 
			
		||||
            var backing = Nullability.assertNonNull(entry.contents);
 | 
			
		||||
            if (position >= backing.length) return -1;
 | 
			
		||||
            if (position >= entry.length) return -1;
 | 
			
		||||
 | 
			
		||||
            var remaining = Math.min(backing.length - (int) position, destination.remaining());
 | 
			
		||||
            var remaining = Math.min(entry.length - (int) position, destination.remaining());
 | 
			
		||||
            destination.put(backing, (int) position, remaining);
 | 
			
		||||
            position += remaining;
 | 
			
		||||
            return remaining;
 | 
			
		||||
@@ -285,7 +285,7 @@ public final class MemoryMount extends AbstractInMemoryMount<MemoryMount.FileEnt
 | 
			
		||||
 | 
			
		||||
        private byte[] ensureCapacity(int capacity) {
 | 
			
		||||
            var contents = Nullability.assertNonNull(entry.contents);
 | 
			
		||||
            if (capacity >= entry.length) {
 | 
			
		||||
            if (capacity >= contents.length) {
 | 
			
		||||
                var newCapacity = Math.max(capacity, contents.length << 1);
 | 
			
		||||
                contents = entry.contents = Arrays.copyOf(contents, newCapacity);
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,6 @@ import org.squiddev.cobalt.lib.Bit32Lib;
 | 
			
		||||
import org.squiddev.cobalt.lib.CoreLibraries;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.Serial;
 | 
			
		||||
import java.nio.ByteBuffer;
 | 
			
		||||
@@ -49,7 +48,7 @@ public class CobaltLuaMachine implements ILuaMachine {
 | 
			
		||||
 | 
			
		||||
    private @Nullable String eventFilter = null;
 | 
			
		||||
 | 
			
		||||
    public CobaltLuaMachine(MachineEnvironment environment, InputStream bios) throws MachineException, IOException {
 | 
			
		||||
    public CobaltLuaMachine(MachineEnvironment environment, InputStream bios) throws MachineException {
 | 
			
		||||
        timeout = environment.timeout();
 | 
			
		||||
        context = environment.context();
 | 
			
		||||
        luaMethods = environment.luaMethods();
 | 
			
		||||
@@ -81,7 +80,7 @@ public class CobaltLuaMachine implements ILuaMachine {
 | 
			
		||||
            globals.rawset("_CC_DEFAULT_SETTINGS", ValueFactory.valueOf(CoreConfig.defaultComputerSettings));
 | 
			
		||||
 | 
			
		||||
            // Add default APIs
 | 
			
		||||
            for (var api : environment.apis()) addAPI(globals, api);
 | 
			
		||||
            for (var api : environment.apis()) addAPI(state, globals, api);
 | 
			
		||||
 | 
			
		||||
            // And load the BIOS
 | 
			
		||||
            var value = LoadState.load(state, bios, "@bios.lua", globals);
 | 
			
		||||
@@ -93,7 +92,7 @@ public class CobaltLuaMachine implements ILuaMachine {
 | 
			
		||||
        timeout.addListener(timeoutListener);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void addAPI(LuaTable globals, ILuaAPI api) {
 | 
			
		||||
    private void addAPI(LuaState state, LuaTable globals, ILuaAPI api) throws LuaError {
 | 
			
		||||
        // Add the methods of an API to the global table
 | 
			
		||||
        var table = wrapLuaObject(api);
 | 
			
		||||
        if (table == null) {
 | 
			
		||||
@@ -103,6 +102,9 @@ public class CobaltLuaMachine implements ILuaMachine {
 | 
			
		||||
 | 
			
		||||
        var names = api.getNames();
 | 
			
		||||
        for (var name : names) globals.rawset(name, table);
 | 
			
		||||
 | 
			
		||||
        var moduleName = api.getModuleName();
 | 
			
		||||
        if (moduleName != null) state.registry().getSubTable(Constants.LOADED).rawset(moduleName, table);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void updateTimeout() {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,11 @@
 | 
			
		||||
# New features in CC: Tweaked 1.109.6
 | 
			
		||||
 | 
			
		||||
* Improve several Lua parser error messages.
 | 
			
		||||
* Allow addon mods to register `require`able modules.
 | 
			
		||||
 | 
			
		||||
Several bug fixes:
 | 
			
		||||
* Fix weak tables becoming malformed when keys are GCed.
 | 
			
		||||
 | 
			
		||||
# New features in CC: Tweaked 1.109.5
 | 
			
		||||
 | 
			
		||||
* Add a new `/computercraft-computer-folder` command to open a computer's folder
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
New features in CC: Tweaked 1.109.5
 | 
			
		||||
New features in CC: Tweaked 1.109.6
 | 
			
		||||
 | 
			
		||||
* Add a new `/computercraft-computer-folder` command to open a computer's folder
 | 
			
		||||
  in singleplayer.
 | 
			
		||||
* Improve several Lua parser error messages.
 | 
			
		||||
* Allow addon mods to register `require`able modules.
 | 
			
		||||
 | 
			
		||||
Several bug fixes:
 | 
			
		||||
* Discard characters being typed into the editor when closing `edit`'s `Run` screen.
 | 
			
		||||
* Fix weak tables becoming malformed when keys are GCed.
 | 
			
		||||
 | 
			
		||||
Type "help changelog" to see the full version history.
 | 
			
		||||
 
 | 
			
		||||
@@ -453,32 +453,53 @@ function errors.local_function_dot(local_start, local_end, dot_start, dot_end)
 | 
			
		||||
    }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--[[- A statement of the form `x.y z`
 | 
			
		||||
--[[- A statement of the form `x.y`
 | 
			
		||||
 | 
			
		||||
@tparam number token The token id.
 | 
			
		||||
@tparam number pos The position right after this name.
 | 
			
		||||
@return The resulting parse error.
 | 
			
		||||
]]
 | 
			
		||||
function errors.standalone_name(pos)
 | 
			
		||||
    expect(1, pos, "number")
 | 
			
		||||
function errors.standalone_name(token, pos)
 | 
			
		||||
    expect(1, token, "number")
 | 
			
		||||
    expect(2, pos, "number")
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        "Unexpected symbol after name.",
 | 
			
		||||
        "Unexpected " .. token_names[token] .. " after name.",
 | 
			
		||||
        annotate(pos),
 | 
			
		||||
        "Did you mean to assign this or call it as a function?",
 | 
			
		||||
    }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--[[- A statement of the form `x.y, z`
 | 
			
		||||
 | 
			
		||||
@tparam number token The token id.
 | 
			
		||||
@tparam number pos The position right after this name.
 | 
			
		||||
@return The resulting parse error.
 | 
			
		||||
]]
 | 
			
		||||
function errors.standalone_names(token, pos)
 | 
			
		||||
    expect(1, token, "number")
 | 
			
		||||
    expect(2, pos, "number")
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        "Unexpected " .. token_names[token] .. " after name.",
 | 
			
		||||
        annotate(pos),
 | 
			
		||||
        "Did you mean to assign this?",
 | 
			
		||||
    }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--[[- A statement of the form `x.y`. This is similar to [`standalone_name`], but
 | 
			
		||||
when the next token is on another line.
 | 
			
		||||
 | 
			
		||||
@tparam number token The token id.
 | 
			
		||||
@tparam number pos The position right after this name.
 | 
			
		||||
@return The resulting parse error.
 | 
			
		||||
]]
 | 
			
		||||
function errors.standalone_name_call(pos)
 | 
			
		||||
    expect(1, pos, "number")
 | 
			
		||||
function errors.standalone_name_call(token, pos)
 | 
			
		||||
    expect(1, token, "number")
 | 
			
		||||
    expect(2, pos, "number")
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        "Unexpected symbol after variable.",
 | 
			
		||||
        "Unexpected " .. token_names[token] .. " after name.",
 | 
			
		||||
        annotate(pos + 1, "Expected something before the end of the line."),
 | 
			
		||||
        "Tip: Use " .. code("()") .. " to call with no arguments.",
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -124,13 +124,22 @@ local function make_package(env, dir)
 | 
			
		||||
    local package = {}
 | 
			
		||||
    package.loaded = {
 | 
			
		||||
        _G = _G,
 | 
			
		||||
        bit32 = bit32,
 | 
			
		||||
        coroutine = coroutine,
 | 
			
		||||
        math = math,
 | 
			
		||||
        package = package,
 | 
			
		||||
        string = string,
 | 
			
		||||
        table = table,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    -- Copy everything from the global package table to this instance.
 | 
			
		||||
    --
 | 
			
		||||
    -- This table is an internal implementation detail - it is NOT intended to
 | 
			
		||||
    -- be extended by user code.
 | 
			
		||||
    local registry = debug.getregistry()
 | 
			
		||||
    if registry and type(registry._LOADED) == "table" then
 | 
			
		||||
        for k, v in next, registry._LOADED do
 | 
			
		||||
            if type(k) == "string" then
 | 
			
		||||
                package.loaded[k] = v
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    package.path = "?;?.lua;?/init.lua;/rom/modules/main/?;/rom/modules/main/?.lua;/rom/modules/main/?/init.lua"
 | 
			
		||||
    if turtle then
 | 
			
		||||
        package.path = package.path .. ";/rom/modules/turtle/?;/rom/modules/turtle/?.lua;/rom/modules/turtle/?/init.lua"
 | 
			
		||||
 
 | 
			
		||||
@@ -89,6 +89,16 @@ public class MethodTest {
 | 
			
		||||
            x -> x.addApi(new ReturnFunction()), 50);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testModule() {
 | 
			
		||||
        ComputerBootstrap.run(
 | 
			
		||||
            """
 | 
			
		||||
            assert(require "test.module".func() == 123)
 | 
			
		||||
            """,
 | 
			
		||||
            x -> x.addApi(new IsModule()), 50);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class MainThread implements ILuaAPI, IPeripheral {
 | 
			
		||||
        public final String thread = Thread.currentThread().getName();
 | 
			
		||||
 | 
			
		||||
@@ -206,7 +216,7 @@ public class MethodTest {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public MethodResult callMethod(ILuaContext context, int method, IArguments arguments) throws LuaException {
 | 
			
		||||
        public MethodResult callMethod(ILuaContext context, int method, IArguments arguments) {
 | 
			
		||||
            return MethodResult.of();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -227,4 +237,21 @@ public class MethodTest {
 | 
			
		||||
            return new String[]{ "func" };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class IsModule implements ILuaAPI {
 | 
			
		||||
        @Override
 | 
			
		||||
        public String[] getNames() {
 | 
			
		||||
            return new String[0];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public @Nullable String getModuleName() {
 | 
			
		||||
            return "test.module";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @LuaFunction
 | 
			
		||||
        public final int func() {
 | 
			
		||||
            return 123;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ import dan200.computercraft.core.computer.mainthread.MainThreadConfig;
 | 
			
		||||
import dan200.computercraft.core.filesystem.MemoryMount;
 | 
			
		||||
import dan200.computercraft.core.terminal.Terminal;
 | 
			
		||||
import dan200.computercraft.test.core.computer.BasicEnvironment;
 | 
			
		||||
import org.intellij.lang.annotations.Language;
 | 
			
		||||
import org.junit.jupiter.api.Assertions;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
@@ -31,7 +32,7 @@ public class ComputerBootstrap {
 | 
			
		||||
    private static final int TPS = 20;
 | 
			
		||||
    public static final int MAX_TIME = 10;
 | 
			
		||||
 | 
			
		||||
    public static void run(String program, Consumer<Computer> setup, int maxTimes) {
 | 
			
		||||
    public static void run(@Language("lua") String program, Consumer<Computer> setup, int maxTimes) {
 | 
			
		||||
        var mount = new MemoryMount()
 | 
			
		||||
            .addFile("test.lua", program)
 | 
			
		||||
            .addFile("startup.lua", "assertion.assert(pcall(loadfile('test.lua', nil, _ENV))) os.shutdown()");
 | 
			
		||||
@@ -39,7 +40,7 @@ public class ComputerBootstrap {
 | 
			
		||||
        run(mount, setup, maxTimes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void run(String program, int maxTimes) {
 | 
			
		||||
    public static void run(@Language("lua") String program, int maxTimes) {
 | 
			
		||||
        run(program, x -> {
 | 
			
		||||
        }, maxTimes);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -347,7 +347,7 @@ function ( xyz , while
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected while.
 | 
			
		||||
Unexpected while. Expected a variable name.
 | 
			
		||||
   |
 | 
			
		||||
 1 | function ( xyz , while
 | 
			
		||||
   |                  ^^^^^
 | 
			
		||||
@@ -483,11 +483,11 @@ xyz , xyz while
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected symbol after name.
 | 
			
		||||
Unexpected while after name.
 | 
			
		||||
   |
 | 
			
		||||
 1 | xyz , xyz while
 | 
			
		||||
   |           ^
 | 
			
		||||
Did you mean to assign this or call it as a function?
 | 
			
		||||
Did you mean to assign this?
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -831,7 +831,7 @@ xyz while
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected symbol after name.
 | 
			
		||||
Unexpected while after name.
 | 
			
		||||
   |
 | 
			
		||||
 1 | xyz while
 | 
			
		||||
   |     ^
 | 
			
		||||
@@ -858,7 +858,7 @@ xyz while
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected symbol after name.
 | 
			
		||||
Unexpected while after name.
 | 
			
		||||
   |
 | 
			
		||||
 1 | xyz while
 | 
			
		||||
   |     ^
 | 
			
		||||
@@ -1056,7 +1056,7 @@ local while
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected while.
 | 
			
		||||
Unexpected while. Expected a variable name.
 | 
			
		||||
   |
 | 
			
		||||
 1 | local while
 | 
			
		||||
   |       ^^^^^
 | 
			
		||||
@@ -1272,7 +1272,7 @@ repeat --[[eof]]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected end of file. Expected a statement.
 | 
			
		||||
Unexpected end of file. Expected a variable name.
 | 
			
		||||
   |
 | 
			
		||||
 2 | -- Line 1: 'until' expected near <eof> (program)
 | 
			
		||||
   |                                                 ^
 | 
			
		||||
@@ -1389,7 +1389,7 @@ while
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected while.
 | 
			
		||||
Unexpected while. Expected an expression.
 | 
			
		||||
   |
 | 
			
		||||
 1 | while
 | 
			
		||||
   | ^^^^^
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,20 @@ Unexpected = in expression.
 | 
			
		||||
Tip: Wrap the preceding expression in [ and ] to use it as a table key.
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
and also
 | 
			
		||||
 | 
			
		||||
```lua
 | 
			
		||||
return { x + 1 = 1 }
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected = in expression.
 | 
			
		||||
   |
 | 
			
		||||
 1 | return { x + 1 = 1 }
 | 
			
		||||
   |                ^
 | 
			
		||||
Tip: Wrap the preceding expression in [ and ] to use it as a table key.
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Note this doesn't occur if this there's already a table key here:
 | 
			
		||||
 | 
			
		||||
```lua
 | 
			
		||||
@@ -102,6 +116,7 @@ Unexpected end of file. Are you missing a closing bracket?
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Missing commas in tables
 | 
			
		||||
We try to detect missing commas in tables, and print an appropriate error message.
 | 
			
		||||
 | 
			
		||||
```lua
 | 
			
		||||
return { 1 2 }
 | 
			
		||||
@@ -129,6 +144,39 @@ Unexpected number in table.
 | 
			
		||||
 1 | return { 1, 2 3 }
 | 
			
		||||
   |              ^ Are you missing a comma here?
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This also works with table keys.
 | 
			
		||||
 | 
			
		||||
```lua
 | 
			
		||||
print({ x = 1 y = 2 })
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected identifier in table.
 | 
			
		||||
   |
 | 
			
		||||
 1 | print({ x = 1 y = 2 })
 | 
			
		||||
   |               ^
 | 
			
		||||
   |
 | 
			
		||||
 1 | print({ x = 1 y = 2 })
 | 
			
		||||
   |              ^ Are you missing a comma here?
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```lua
 | 
			
		||||
print({ ["x"] = 1 ["y"] = 2 })
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected [ in table.
 | 
			
		||||
   |
 | 
			
		||||
 1 | print({ ["x"] = 1 ["y"] = 2 })
 | 
			
		||||
   |                   ^
 | 
			
		||||
   |
 | 
			
		||||
 1 | print({ ["x"] = 1 ["y"] = 2 })
 | 
			
		||||
   |                  ^ Are you missing a comma here?
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
We gracefully handle the case where we are actually missing a closing brace.
 | 
			
		||||
 | 
			
		||||
```lua
 | 
			
		||||
print({ 1, )
 | 
			
		||||
```
 | 
			
		||||
@@ -172,7 +220,7 @@ local _ = 1
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected symbol after variable.
 | 
			
		||||
Unexpected local after name.
 | 
			
		||||
   |
 | 
			
		||||
 1 | term.clear
 | 
			
		||||
   |           ^ Expected something before the end of the line.
 | 
			
		||||
@@ -186,7 +234,7 @@ x 1
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected symbol after name.
 | 
			
		||||
Unexpected number after name.
 | 
			
		||||
   |
 | 
			
		||||
 1 | x 1
 | 
			
		||||
   |   ^
 | 
			
		||||
@@ -200,13 +248,41 @@ term.clear
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected symbol after variable.
 | 
			
		||||
Unexpected end of file after name.
 | 
			
		||||
   |
 | 
			
		||||
 1 | term.clear
 | 
			
		||||
   |           ^ Expected something before the end of the line.
 | 
			
		||||
Tip: Use () to call with no arguments.
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
When we've got a list of variables, we only suggest assigning it.
 | 
			
		||||
 | 
			
		||||
```lua
 | 
			
		||||
term.clear, foo
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected end of file after name.
 | 
			
		||||
   |
 | 
			
		||||
 1 | term.clear, foo
 | 
			
		||||
   |                ^
 | 
			
		||||
Did you mean to assign this?
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
And when we've got a partial expression, we only suggest calling it.
 | 
			
		||||
 | 
			
		||||
```lua
 | 
			
		||||
(a + b)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected end of file after name.
 | 
			
		||||
   |
 | 
			
		||||
 1 | (a + b)
 | 
			
		||||
   |        ^ Expected something before the end of the line.
 | 
			
		||||
Tip: Use () to call with no arguments.
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## If statements
 | 
			
		||||
For if statements, we say when we expected the `then` keyword.
 | 
			
		||||
 | 
			
		||||
@@ -425,7 +501,7 @@ goto 2
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected symbol after name.
 | 
			
		||||
Unexpected number after name.
 | 
			
		||||
   |
 | 
			
		||||
 1 | goto 2
 | 
			
		||||
   |      ^
 | 
			
		||||
@@ -460,6 +536,31 @@ Unexpected end of file.
 | 
			
		||||
   |   ^
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Missing function arguments
 | 
			
		||||
We provide an error message for missing arguments in function definitions:
 | 
			
		||||
 | 
			
		||||
```lua
 | 
			
		||||
function f
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected end of file. Expected ( to start function arguments.
 | 
			
		||||
   |
 | 
			
		||||
 1 | function f
 | 
			
		||||
   |           ^
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```lua
 | 
			
		||||
return function
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```txt
 | 
			
		||||
Unexpected end of file. Expected ( to start function arguments.
 | 
			
		||||
   |
 | 
			
		||||
 1 | return function
 | 
			
		||||
   |                ^
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
# Function calls
 | 
			
		||||
 | 
			
		||||
## Additional commas
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user