mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-04-14 06:43:16 +00:00
Update Cobalt to 0.8.0
- Update Cobalt to 0.8.0, switching our Lua version to 5.2(ish). - Remove our `load` wrapper, as we no longer need to inject _ENV into the enviroment table. - Update the parser to handle labels and goto. This doesn't check that gotos are well formed, but at least means the parser doesn't fall over on them. - Update our docs to reflect the changes to Cobalt.
This commit is contained in:
parent
bcb3e9bd53
commit
784e623776
@ -57,7 +57,6 @@ repositories {
|
||||
|
||||
filter {
|
||||
includeGroup("cc.tweaked")
|
||||
includeModule("org.squiddev", "Cobalt")
|
||||
// Things we mirror
|
||||
includeGroup("commoble.morered")
|
||||
includeGroup("dev.architectury")
|
||||
|
@ -21,6 +21,17 @@ of the mod should run fine on later versions.
|
||||
However, some changes to the underlying game, or CC: Tweaked's own internals may break some programs. This page serves
|
||||
as documentation for breaking changes and "gotchas" one should look out for between versions.
|
||||
|
||||
## CC: Tweaked 1.109.0 {#cct-1.109}
|
||||
|
||||
- Update to Lua 5.2:
|
||||
- Support for Lua 5.0's pseudo-argument `arg` has been removed. You should always use `...` for varargs.
|
||||
- Environments are no longer baked into the runtime, and instead use the `_ENV` local or upvalue. `getfenv`/`setfenv`
|
||||
now only work on Lua functions with an `_ENV` upvalue. `getfenv` will return the global environment when called
|
||||
with other functions, and `setfenv` will have no effect.
|
||||
- `load`/`loadstring` defaults to using the global environment (`_G`) rather than the current coroutine's
|
||||
environment.
|
||||
- Support for dumping functions (`string.dump`) and loading binary chunks has been removed.
|
||||
|
||||
## Minecraft 1.13 {#mc-1.13}
|
||||
- The "key code" for [`key`] and [`key_up`] events has changed, due to Minecraft updating to LWJGL 3. Make sure you're
|
||||
using the constants provided by the [`keys`] API, rather than hard-coding numerical values.
|
||||
|
@ -9,17 +9,19 @@ SPDX-License-Identifier: MPL-2.0
|
||||
-->
|
||||
|
||||
# Lua 5.2/5.3 features in CC: Tweaked
|
||||
CC: Tweaked is based off of the Cobalt Lua runtime, which uses Lua 5.1. However, Cobalt and CC:T implement additional features from Lua 5.2 and 5.3 (as well as some deprecated 5.0 features) that are not available in base 5.1. This page lists all of the compatibility for these newer versions.
|
||||
CC: Tweaked is based off of the Cobalt Lua runtime, which uses Lua 5.2. However, Cobalt and CC:T implement additional
|
||||
features from Lua 5.2 and 5.3 (as well as some deprecated 5.0 and 5.1 features). This page lists all of the
|
||||
compatibility for these newer versions.
|
||||
|
||||
## Lua 5.2
|
||||
| Feature | Supported? | Notes |
|
||||
|---------------------------------------------------------------|------------|-------------------------------------------------------------------|
|
||||
| `goto`/labels | ❌ | |
|
||||
| `_ENV` | 🔶 | The `_ENV` global points to `getfenv()`, but it cannot be set. |
|
||||
| `goto`/labels | ✔ | |
|
||||
| `_ENV` | ✔ | |
|
||||
| `\z` escape | ✔ | |
|
||||
| `\xNN` escape | ✔ | |
|
||||
| Hex literal fractional/exponent parts | ✔ | |
|
||||
| Empty statements | ❌ | |
|
||||
| Empty statements | ✔ | |
|
||||
| `__len` metamethod | ✔ | |
|
||||
| `__ipairs` metamethod | ❌ | Deprecated in Lua 5.3. `ipairs` uses `__len`/`__index` instead. |
|
||||
| `__pairs` metamethod | ✔ | |
|
||||
@ -27,12 +29,12 @@ CC: Tweaked is based off of the Cobalt Lua runtime, which uses Lua 5.1. However,
|
||||
| `collectgarbage` isrunning, generational, incremental options | ❌ | `collectgarbage` does not exist in CC:T. |
|
||||
| New `load` syntax | ✔ | |
|
||||
| `loadfile` mode parameter | ✔ | Supports both 5.1 and 5.2+ syntax. |
|
||||
| Removed `loadstring` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
||||
| Removed `getfenv`, `setfenv` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
||||
| Removed `loadstring` | ❌ | |
|
||||
| Removed `getfenv`, `setfenv` | 🔶 | Only supports closures with an `_ENV` upvalue. |
|
||||
| `rawlen` function | ✔ | |
|
||||
| Negative index to `select` | ✔ | |
|
||||
| Removed `unpack` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
||||
| Arguments to `xpcall` | ✔ | |
|
||||
| Removed `unpack` | ❌ | |
|
||||
| Arguments to `xpcall` | ✔ | |
|
||||
| Second return value from `coroutine.running` | ✔ | |
|
||||
| Removed `module` | ✔ | |
|
||||
| `package.loaders` -> `package.searchers` | ❌ | |
|
||||
@ -40,14 +42,14 @@ CC: Tweaked is based off of the Cobalt Lua runtime, which uses Lua 5.1. However,
|
||||
| `package.config` | ✔ | |
|
||||
| `package.searchpath` | ✔ | |
|
||||
| Removed `package.seeall` | ✔ | |
|
||||
| `string.dump` on functions with upvalues (blanks them out) | ✔ | |
|
||||
| `string.rep` separator | ✔ | |
|
||||
| `string.dump` on functions with upvalues (blanks them out) | ❌ | `string.dump` is not supported |
|
||||
| `string.rep` separator | ✔ | |
|
||||
| `%g` match group | ❌ | |
|
||||
| Removal of `%z` match group | ❌ | |
|
||||
| Removed `table.maxn` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
||||
| Removed `table.maxn` | ❌ | |
|
||||
| `table.pack`/`table.unpack` | ✔ | |
|
||||
| `math.log` base argument | ✔ | |
|
||||
| Removed `math.log10` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
||||
| Removed `math.log10` | ❌ | |
|
||||
| `*L` mode to `file:read` | ✔ | |
|
||||
| `os.execute` exit type + return value | ❌ | `os.execute` does not exist in CC:T. |
|
||||
| `os.exit` close argument | ❌ | `os.exit` does not exist in CC:T. |
|
||||
@ -61,7 +63,7 @@ CC: Tweaked is based off of the Cobalt Lua runtime, which uses Lua 5.1. However,
|
||||
| Tail call hooks | ❌ | |
|
||||
| `=` prefix for chunks | ✔ | |
|
||||
| Yield across C boundary | ✔ | |
|
||||
| Removal of ambiguity error | ❌ | |
|
||||
| Removal of ambiguity error | ✔ | |
|
||||
| Identifiers may no longer use locale-dependent letters | ✔ | |
|
||||
| Ephemeron tables | ❌ | |
|
||||
| Identical functions may be reused | ❌ | Removed in Lua 5.4 |
|
||||
|
@ -19,8 +19,8 @@ parchmentMc = "1.20.1"
|
||||
asm = "9.5"
|
||||
autoService = "1.1.1"
|
||||
checkerFramework = "3.32.0"
|
||||
cobalt = "0.7.3"
|
||||
cobalt-next = "0.7.4" # Not a real version, used to constrain the version we accept.
|
||||
cobalt = "0.8.0"
|
||||
cobalt-next = "0.8.1" # Not a real version, used to constrain the version we accept.
|
||||
commonsCli = "1.3.1"
|
||||
fastutil = "8.5.9"
|
||||
guava = "31.1-jre"
|
||||
@ -51,7 +51,7 @@ jqwik = "1.7.4"
|
||||
junit = "5.10.0"
|
||||
|
||||
# Build tools
|
||||
cctJavadoc = "1.8.0"
|
||||
cctJavadoc = "1.8.1"
|
||||
checkstyle = "10.12.3"
|
||||
curseForgeGradle = "1.0.14"
|
||||
errorProne-core = "2.21.1"
|
||||
@ -68,7 +68,7 @@ mixinGradle = "0.7.+"
|
||||
nullAway = "0.9.9"
|
||||
spotless = "6.21.0"
|
||||
taskTree = "2.1.1"
|
||||
teavm = "0.9.0-SQUID.1"
|
||||
teavm = "0.10.0-SQUID.1"
|
||||
vanillaGradle = "0.2.1-SNAPSHOT"
|
||||
vineflower = "1.11.0"
|
||||
|
||||
@ -78,7 +78,7 @@ asm = { module = "org.ow2.asm:asm", version.ref = "asm" }
|
||||
asm-commons = { module = "org.ow2.asm:asm-commons", version.ref = "asm" }
|
||||
autoService = { module = "com.google.auto.service:auto-service", version.ref = "autoService" }
|
||||
checkerFramework = { module = "org.checkerframework:checker-qual", version.ref = "checkerFramework" }
|
||||
cobalt = { module = "org.squiddev:Cobalt", version.ref = "cobalt" }
|
||||
cobalt = { module = "cc.tweaked:cobalt", version.ref = "cobalt" }
|
||||
commonsCli = { module = "commons-cli:commons-cli", version.ref = "commonsCli" }
|
||||
fastutil = { module = "it.unimi.dsi:fastutil", version.ref = "fastutil" }
|
||||
forgeSpi = { module = "net.minecraftforge:forgespi", version.ref = "forgeSpi" }
|
||||
|
@ -73,20 +73,20 @@ public class CobaltLuaMachine implements ILuaMachine {
|
||||
.build();
|
||||
|
||||
// Set up our global table.
|
||||
var globals = state.getMainThread().getfenv();
|
||||
CoreLibraries.debugGlobals(state);
|
||||
Bit32Lib.add(state, globals);
|
||||
globals.rawset("_HOST", ValueFactory.valueOf(environment.hostString()));
|
||||
globals.rawset("_CC_DEFAULT_SETTINGS", ValueFactory.valueOf(CoreConfig.defaultComputerSettings));
|
||||
|
||||
// Add default APIs
|
||||
for (var api : environment.apis()) addAPI(globals, api);
|
||||
|
||||
// And load the BIOS
|
||||
try {
|
||||
var globals = state.globals();
|
||||
CoreLibraries.debugGlobals(state);
|
||||
Bit32Lib.add(state, globals);
|
||||
globals.rawset("_HOST", ValueFactory.valueOf(environment.hostString()));
|
||||
globals.rawset("_CC_DEFAULT_SETTINGS", ValueFactory.valueOf(CoreConfig.defaultComputerSettings));
|
||||
|
||||
// Add default APIs
|
||||
for (var api : environment.apis()) addAPI(globals, api);
|
||||
|
||||
// And load the BIOS
|
||||
var value = LoadState.load(state, bios, "@bios.lua", globals);
|
||||
mainRoutine = new LuaThread(state, value, globals);
|
||||
} catch (CompileException e) {
|
||||
mainRoutine = new LuaThread(state, value);
|
||||
} catch (LuaError | CompileException e) {
|
||||
throw new MachineException(Nullability.assertNonNull(e.getMessage()));
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ public class CobaltLuaMachine implements ILuaMachine {
|
||||
return found ? table : null;
|
||||
}
|
||||
|
||||
private LuaValue toValue(@Nullable Object object, @Nullable IdentityHashMap<Object, LuaValue> values) {
|
||||
private LuaValue toValue(@Nullable Object object, @Nullable IdentityHashMap<Object, LuaValue> values) throws LuaError {
|
||||
if (object == null) return Constants.NIL;
|
||||
if (object instanceof Number num) return ValueFactory.valueOf(num.doubleValue());
|
||||
if (object instanceof Boolean bool) return ValueFactory.valueOf(bool);
|
||||
@ -235,7 +235,7 @@ public class CobaltLuaMachine implements ILuaMachine {
|
||||
return Constants.NIL;
|
||||
}
|
||||
|
||||
Varargs toValues(@Nullable Object[] objects) {
|
||||
Varargs toValues(@Nullable Object[] objects) throws LuaError {
|
||||
if (objects == null || objects.length == 0) return Constants.NONE;
|
||||
if (objects.length == 1) return toValue(objects[0], null);
|
||||
|
||||
|
@ -18,33 +18,6 @@ do
|
||||
expect = f().expect
|
||||
end
|
||||
|
||||
if _VERSION == "Lua 5.1" then
|
||||
-- If we're on Lua 5.1, install parts of the Lua 5.2/5.3 API so that programs can be written against it
|
||||
local nativeload = load
|
||||
|
||||
function load(x, name, mode, env)
|
||||
expect(1, x, "function", "string")
|
||||
expect(2, name, "string", "nil")
|
||||
expect(3, mode, "string", "nil")
|
||||
expect(4, env, "table", "nil")
|
||||
|
||||
local ok, p1, p2 = pcall(function()
|
||||
local result, err = nativeload(x, name, mode, env)
|
||||
if result and env then
|
||||
env._ENV = env
|
||||
end
|
||||
return result, err
|
||||
end)
|
||||
if ok then
|
||||
return p1, p2
|
||||
else
|
||||
error(p1, 2)
|
||||
end
|
||||
end
|
||||
|
||||
loadstring = function(string, chunkname) return nativeload(string, chunkname) end
|
||||
end
|
||||
|
||||
-- Inject a stub for the old bit library
|
||||
_G.bit = {
|
||||
bnot = bit32.bnot,
|
||||
|
@ -535,6 +535,28 @@ function errors.unexpected_end(start_pos, end_pos)
|
||||
}
|
||||
end
|
||||
|
||||
--[[- A label statement was opened but not closed.
|
||||
|
||||
@tparam number open_start The start position of the opening label.
|
||||
@tparam number open_end The end position of the opening label.
|
||||
@tparam number tok_start The start position of the current token.
|
||||
@return The resulting parse error.
|
||||
]]
|
||||
function errors.unclosed_label(open_start, open_end, token, start_pos, end_pos)
|
||||
expect(1, open_start, "number")
|
||||
expect(2, open_end, "number")
|
||||
expect(3, token, "number")
|
||||
expect(4, start_pos, "number")
|
||||
expect(5, end_pos, "number")
|
||||
|
||||
return {
|
||||
"Unexpected " .. token_names[token] .. ".",
|
||||
annotate(open_start, open_end, "Label was started here."),
|
||||
annotate(start_pos, end_pos, "Tip: Try adding " .. code("::") .. " here."),
|
||||
|
||||
}
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Generic parsing errors
|
||||
--------------------------------------------------------------------------------
|
||||
|
@ -32,12 +32,12 @@ local tokens = require "cc.internal.syntax.parser".tokens
|
||||
local sub, find = string.sub, string.find
|
||||
|
||||
local keywords = {
|
||||
["and"] = tokens.AND, ["break"] = tokens.BREAK, ["do"] = tokens.DO, ["else"] = tokens.ELSE,
|
||||
["elseif"] = tokens.ELSEIF, ["end"] = tokens.END, ["false"] = tokens.FALSE, ["for"] = tokens.FOR,
|
||||
["function"] = tokens.FUNCTION, ["if"] = tokens.IF, ["in"] = tokens.IN, ["local"] = tokens.LOCAL,
|
||||
["nil"] = tokens.NIL, ["not"] = tokens.NOT, ["or"] = tokens.OR, ["repeat"] = tokens.REPEAT,
|
||||
["return"] = tokens.RETURN, ["then"] = tokens.THEN, ["true"] = tokens.TRUE, ["until"] = tokens.UNTIL,
|
||||
["while"] = tokens.WHILE,
|
||||
["and"] = tokens.AND, ["break"] = tokens.BREAK, ["do"] = tokens.DO, ["else"] = tokens.ELSE,
|
||||
["elseif"] = tokens.ELSEIF, ["end"] = tokens.END, ["false"] = tokens.FALSE, ["for"] = tokens.FOR,
|
||||
["function"] = tokens.FUNCTION, ["goto"] = tokens.GOTO, ["if"] = tokens.IF, ["in"] = tokens.IN,
|
||||
["local"] = tokens.LOCAL, ["nil"] = tokens.NIL, ["not"] = tokens.NOT, ["or"] = tokens.OR,
|
||||
["repeat"] = tokens.REPEAT, ["return"] = tokens.RETURN, ["then"] = tokens.THEN, ["true"] = tokens.TRUE,
|
||||
["until"] = tokens.UNTIL, ["while"] = tokens.WHILE,
|
||||
}
|
||||
|
||||
--- Lex a newline character
|
||||
@ -292,12 +292,15 @@ local function lex_token(context, str, pos)
|
||||
local next_pos = pos + 1
|
||||
if sub(str, next_pos, next_pos) == "=" then return tokens.LE, next_pos end
|
||||
return tokens.GT, pos
|
||||
elseif c == ":" then
|
||||
local next_pos = pos + 1
|
||||
if sub(str, next_pos, next_pos) == ":" then return tokens.DOUBLE_COLON, next_pos end
|
||||
return tokens.COLON, pos
|
||||
elseif c == "~" and sub(str, pos + 1, pos + 1) == "=" then return tokens.NE, pos + 1
|
||||
|
||||
-- Single character tokens
|
||||
elseif c == "," then return tokens.COMMA, pos
|
||||
elseif c == ";" then return tokens.SEMICOLON, pos
|
||||
elseif c == ":" then return tokens.COLON, pos
|
||||
elseif c == "(" then return tokens.OPAREN, pos
|
||||
elseif c == ")" then return tokens.CPAREN, pos
|
||||
elseif c == "]" then return tokens.CSQUARE, pos
|
||||
|
File diff suppressed because one or more lines are too long
@ -10,6 +10,8 @@ import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.squiddev.cobalt.LuaError;
|
||||
import org.squiddev.cobalt.LuaState;
|
||||
import org.squiddev.cobalt.Prototype;
|
||||
import org.squiddev.cobalt.compiler.CompileException;
|
||||
import org.squiddev.cobalt.compiler.LuaC;
|
||||
@ -108,9 +110,9 @@ class LuaCoverage {
|
||||
Queue<Prototype> queue = new ArrayDeque<>();
|
||||
|
||||
try (InputStream stream = new FileInputStream(file)) {
|
||||
var proto = LuaC.compile(stream, "@" + file.getPath());
|
||||
var proto = LuaC.compile(new LuaState(), stream, "@" + file.getPath());
|
||||
queue.add(proto);
|
||||
} catch (CompileException e) {
|
||||
} catch (LuaError | CompileException e) {
|
||||
throw new IllegalStateException("Cannot compile", e);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ package dan200.computercraft.core.lua;
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.squiddev.cobalt.Constants;
|
||||
import org.squiddev.cobalt.LuaError;
|
||||
import org.squiddev.cobalt.LuaTable;
|
||||
import org.squiddev.cobalt.ValueFactory;
|
||||
|
||||
@ -18,7 +19,11 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
class VarargArgumentsTest {
|
||||
private static LuaTable tableWithCustomType() {
|
||||
var metatable = new LuaTable();
|
||||
metatable.rawset(Constants.NAME, ValueFactory.valueOf("some type"));
|
||||
try {
|
||||
metatable.rawset(Constants.NAME, ValueFactory.valueOf("some type"));
|
||||
} catch (LuaError e) {
|
||||
throw new IllegalStateException("Cannot create metatable", e);
|
||||
}
|
||||
|
||||
var table = new LuaTable();
|
||||
table.setMetatable(null, metatable);
|
||||
|
@ -188,6 +188,9 @@ local function format(value)
|
||||
-- TODO: Look into something like mbs's pretty printer.
|
||||
if type(value) == "string" and value:find("\n") then
|
||||
return "<<<\n" .. value .. "\n>>>"
|
||||
elseif type(value) == "string" then
|
||||
local escaped = value:gsub("[^%g ]", function(x) return ("\\x%02x"):format(x:byte()) end)
|
||||
return "\"" .. escaped .. "\""
|
||||
else
|
||||
local ok, res = pcall(textutils.serialise, value)
|
||||
if ok then return res else return tostring(value) end
|
||||
|
@ -79,20 +79,6 @@ describe("The Lua base library", function()
|
||||
end)
|
||||
|
||||
describe("load", function()
|
||||
it("validates arguments", function()
|
||||
load("")
|
||||
load(function()
|
||||
end)
|
||||
load("", "")
|
||||
load("", "", "")
|
||||
load("", "", "", _ENV)
|
||||
|
||||
expect.error(load, nil):eq("bad argument #1 (function or string expected, got nil)")
|
||||
expect.error(load, "", false):eq("bad argument #2 (string expected, got boolean)")
|
||||
expect.error(load, "", "", false):eq("bad argument #3 (string expected, got boolean)")
|
||||
expect.error(load, "", "", "", false):eq("bad argument #4 (table expected, got boolean)")
|
||||
end)
|
||||
|
||||
local function generator(parts)
|
||||
return coroutine.wrap(function()
|
||||
for i = 1, #parts do
|
||||
|
@ -8,32 +8,6 @@ An exhaustive list of all error states in the parser, and the error messages we
|
||||
generate for each one. This is _not_ a complete collection of all possible
|
||||
errors, but is a useful guide for where we might be providing terrible messages.
|
||||
|
||||
```lua
|
||||
break while
|
||||
-- Line 1: unexpected symbol near <eof> (program)
|
||||
```
|
||||
|
||||
```txt
|
||||
Unexpected while. Expected a statement.
|
||||
|
|
||||
1 | break while
|
||||
| ^^^^^
|
||||
```
|
||||
|
||||
|
||||
```lua
|
||||
do end true
|
||||
-- Line 1: unexpected symbol near 'true' (program)
|
||||
```
|
||||
|
||||
```txt
|
||||
Unexpected true. Expected a statement.
|
||||
|
|
||||
1 | do end true
|
||||
| ^^^^
|
||||
```
|
||||
|
||||
|
||||
```lua
|
||||
do until
|
||||
-- Line 1: 'end' expected near 'until' (program)
|
||||
@ -63,6 +37,35 @@ Unexpected true.
|
||||
```
|
||||
|
||||
|
||||
```lua
|
||||
:: xyz while
|
||||
-- Line 1: '::' expected near 'while' (program)
|
||||
```
|
||||
|
||||
```txt
|
||||
Unexpected while.
|
||||
|
|
||||
1 | :: xyz while
|
||||
| ^^ Label was started here.
|
||||
|
|
||||
1 | :: xyz while
|
||||
| ^^^^^ Tip: Try adding :: here.
|
||||
```
|
||||
|
||||
|
||||
```lua
|
||||
:: while
|
||||
-- Line 1: <name> expected near 'while' (program)
|
||||
```
|
||||
|
||||
```txt
|
||||
Unexpected while.
|
||||
|
|
||||
1 | :: while
|
||||
| ^^^^^
|
||||
```
|
||||
|
||||
|
||||
```lua
|
||||
for xyz , xyz while
|
||||
-- Line 1: 'in' expected near 'while' (program)
|
||||
@ -849,6 +852,20 @@ Unexpected while.
|
||||
```
|
||||
|
||||
|
||||
```lua
|
||||
xyz while
|
||||
-- Line 1: syntax error near 'while' (program)
|
||||
```
|
||||
|
||||
```txt
|
||||
Unexpected symbol after name.
|
||||
|
|
||||
1 | xyz while
|
||||
| ^
|
||||
Did you mean to assign this or call it as a function?
|
||||
```
|
||||
|
||||
|
||||
```lua
|
||||
if xyz then else until
|
||||
-- Line 1: 'end' expected near 'until' (program)
|
||||
@ -1059,22 +1076,6 @@ Unexpected while. Expected an expression.
|
||||
```
|
||||
|
||||
|
||||
```lua {repl_exprs}
|
||||
{ xyz , while
|
||||
-- Line 1: unexpected symbol near 'while' (repl_exprs)
|
||||
```
|
||||
|
||||
```txt
|
||||
Unexpected while. Are you missing a closing bracket?
|
||||
|
|
||||
1 | { xyz , while
|
||||
| ^ Brackets were opened here.
|
||||
|
|
||||
1 | { xyz , while
|
||||
| ^^^^^ Unexpected while here.
|
||||
```
|
||||
|
||||
|
||||
```lua {repl_exprs}
|
||||
{ xyz = xyz while
|
||||
-- Line 1: '}' expected near 'while' (repl_exprs)
|
||||
@ -1104,6 +1105,22 @@ Unexpected while. Expected an expression.
|
||||
```
|
||||
|
||||
|
||||
```lua {repl_exprs}
|
||||
{ xyz ; while
|
||||
-- Line 1: unexpected symbol near 'while' (repl_exprs)
|
||||
```
|
||||
|
||||
```txt
|
||||
Unexpected while. Are you missing a closing bracket?
|
||||
|
|
||||
1 | { xyz ; while
|
||||
| ^ Brackets were opened here.
|
||||
|
|
||||
1 | { xyz ; while
|
||||
| ^^^^^ Unexpected while here.
|
||||
```
|
||||
|
||||
|
||||
```lua {repl_exprs}
|
||||
{ xyz while
|
||||
-- Line 1: '}' expected near 'while' (repl_exprs)
|
||||
|
@ -417,6 +417,49 @@ Unexpected end.
|
||||
Your program contains more ends than needed. Check each block (if, for, function, ...) only has one end.
|
||||
```
|
||||
|
||||
## `goto` and labels
|
||||
We `goto` the same as normal identifiers.
|
||||
|
||||
```lua
|
||||
goto 2
|
||||
```
|
||||
|
||||
```txt
|
||||
Unexpected symbol after name.
|
||||
|
|
||||
1 | goto 2
|
||||
| ^
|
||||
Did you mean to assign this or call it as a function?
|
||||
```
|
||||
|
||||
Labels have a basic closing check:
|
||||
```lua
|
||||
::foo
|
||||
```
|
||||
|
||||
```txt
|
||||
Unexpected end of file.
|
||||
|
|
||||
1 | ::foo
|
||||
| ^^ Label was started here.
|
||||
|
|
||||
1 | ::foo
|
||||
| ^ Tip: Try adding :: here.
|
||||
```
|
||||
|
||||
But we do nothing fancy for just a `::`
|
||||
|
||||
```lua
|
||||
::
|
||||
```
|
||||
|
||||
```txt
|
||||
Unexpected end of file.
|
||||
|
|
||||
1 | ::
|
||||
| ^
|
||||
```
|
||||
|
||||
# Function calls
|
||||
|
||||
## Additional commas
|
||||
|
Loading…
x
Reference in New Issue
Block a user