mirror of
https://github.com/luau-lang/luau.git
synced 2024-11-15 22:35:43 +08:00
Merge branch 'master' into merge
This commit is contained in:
commit
e0af631169
@ -714,7 +714,7 @@ void BytecodeBuilder::writeLineInfo(std::string& ss) const
|
|||||||
// third pass: write resulting data
|
// third pass: write resulting data
|
||||||
int logspan = log2(span);
|
int logspan = log2(span);
|
||||||
|
|
||||||
writeByte(ss, logspan);
|
writeByte(ss, uint8_t(logspan));
|
||||||
|
|
||||||
uint8_t lastOffset = 0;
|
uint8_t lastOffset = 0;
|
||||||
|
|
||||||
@ -723,8 +723,8 @@ void BytecodeBuilder::writeLineInfo(std::string& ss) const
|
|||||||
int delta = lines[i] - baseline[i >> logspan];
|
int delta = lines[i] - baseline[i >> logspan];
|
||||||
LUAU_ASSERT(delta >= 0 && delta <= 255);
|
LUAU_ASSERT(delta >= 0 && delta <= 255);
|
||||||
|
|
||||||
writeByte(ss, delta - lastOffset);
|
writeByte(ss, uint8_t(delta) - lastOffset);
|
||||||
lastOffset = delta;
|
lastOffset = uint8_t(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
int lastLine = 0;
|
int lastLine = 0;
|
||||||
|
@ -364,12 +364,12 @@ struct Compiler
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
args[i] = uint8_t(regs + 1 + i);
|
args[i] = uint8_t(regs + 1 + i);
|
||||||
compileExprTempTop(expr->args.data[i], args[i]);
|
compileExprTempTop(expr->args.data[i], uint8_t(args[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fastcallLabel = bytecode.emitLabel();
|
fastcallLabel = bytecode.emitLabel();
|
||||||
bytecode.emitABC(opc, uint8_t(bfid), args[0], 0);
|
bytecode.emitABC(opc, uint8_t(bfid), uint8_t(args[0]), 0);
|
||||||
if (opc != LOP_FASTCALL1)
|
if (opc != LOP_FASTCALL1)
|
||||||
bytecode.emitAux(args[1]);
|
bytecode.emitAux(args[1]);
|
||||||
|
|
||||||
@ -385,7 +385,7 @@ struct Compiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (args[i] != regs + 1 + i)
|
if (args[i] != regs + 1 + i)
|
||||||
bytecode.emitABC(LOP_MOVE, uint8_t(regs + 1 + i), args[i], 0);
|
bytecode.emitABC(LOP_MOVE, uint8_t(regs + 1 + i), uint8_t(args[i]), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -471,7 +471,7 @@ struct Compiler
|
|||||||
|
|
||||||
if (cid >= 0 && cid < 32768)
|
if (cid >= 0 && cid < 32768)
|
||||||
{
|
{
|
||||||
bytecode.emitAD(LOP_DUPCLOSURE, target, cid);
|
bytecode.emitAD(LOP_DUPCLOSURE, target, int16_t(cid));
|
||||||
shared = true;
|
shared = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -493,7 +493,7 @@ struct Compiler
|
|||||||
// get local variable
|
// get local variable
|
||||||
uint8_t reg = getLocal(uv);
|
uint8_t reg = getLocal(uv);
|
||||||
|
|
||||||
bytecode.emitABC(LOP_CAPTURE, immutable ? LCT_VAL : LCT_REF, reg, 0);
|
bytecode.emitABC(LOP_CAPTURE, uint8_t(immutable ? LCT_VAL : LCT_REF), reg, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -635,7 +635,7 @@ struct Compiler
|
|||||||
|
|
||||||
if (expr->op == AstExprBinary::CompareGt || expr->op == AstExprBinary::CompareGe)
|
if (expr->op == AstExprBinary::CompareGt || expr->op == AstExprBinary::CompareGe)
|
||||||
{
|
{
|
||||||
bytecode.emitAD(opc, rr, 0);
|
bytecode.emitAD(opc, uint8_t(rr), 0);
|
||||||
bytecode.emitAux(rl);
|
bytecode.emitAux(rl);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1144,7 +1144,7 @@ struct Compiler
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bytecode.emitABC(LOP_NEWTABLE, reg, encodedHashSize, 0);
|
bytecode.emitABC(LOP_NEWTABLE, reg, uint8_t(encodedHashSize), 0);
|
||||||
bytecode.emitAux(0);
|
bytecode.emitAux(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1157,7 +1157,7 @@ struct Compiler
|
|||||||
bool trailingVarargs = last && last->kind == AstExprTable::Item::List && last->value->is<AstExprVarargs>();
|
bool trailingVarargs = last && last->kind == AstExprTable::Item::List && last->value->is<AstExprVarargs>();
|
||||||
LUAU_ASSERT(!trailingVarargs || arraySize > 0);
|
LUAU_ASSERT(!trailingVarargs || arraySize > 0);
|
||||||
|
|
||||||
bytecode.emitABC(LOP_NEWTABLE, reg, encodedHashSize, 0);
|
bytecode.emitABC(LOP_NEWTABLE, reg, uint8_t(encodedHashSize), 0);
|
||||||
bytecode.emitAux(arraySize - trailingVarargs + indexSize);
|
bytecode.emitAux(arraySize - trailingVarargs + indexSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ Floor division is less harmful, but it's used rarely enough that `math.floor(a/b
|
|||||||
| const variables | ❌ | while there's some demand for const variables, we'd never adopt this syntax |
|
| const variables | ❌ | while there's some demand for const variables, we'd never adopt this syntax |
|
||||||
| new implementation for math.random | ✔️ | our RNG is based on PCG, unlike Lua 5.4 which uses Xoroshiro |
|
| new implementation for math.random | ✔️ | our RNG is based on PCG, unlike Lua 5.4 which uses Xoroshiro |
|
||||||
| optional `init` argument to `string.gmatch` | 🤷♀️ | no strong use cases |
|
| optional `init` argument to `string.gmatch` | 🤷♀️ | no strong use cases |
|
||||||
| new functions `lua_resetthread` and `coroutine.close` | 🤷 | not useful without to-be-closed variables |
|
| new functions `lua_resetthread` and `coroutine.close` | ✔️ ||
|
||||||
| coercions string-to-number moved to the string library | 😞 | we love this, but it breaks compatibility |
|
| coercions string-to-number moved to the string library | 😞 | we love this, but it breaks compatibility |
|
||||||
| new format `%p` in `string.format` | 🤷♀️ | no strong use cases |
|
| new format `%p` in `string.format` | 🤷♀️ | no strong use cases |
|
||||||
| `utf8` library accepts codepoints up to 2^31 | 🤷♀️ | no strong use cases |
|
| `utf8` library accepts codepoints up to 2^31 | 🤷♀️ | no strong use cases |
|
||||||
@ -127,4 +127,5 @@ We have a few behavior deviations from Lua 5.x that come from either a different
|
|||||||
* Tail calls are not supported to simplify implementation, make debugging/stack traces more predictable and allow deep validation of caller identity for security
|
* Tail calls are not supported to simplify implementation, make debugging/stack traces more predictable and allow deep validation of caller identity for security
|
||||||
* Order of table assignment in table literals follows program order in mixed tables (Lua 5.x assigns array elements first in some cases)
|
* Order of table assignment in table literals follows program order in mixed tables (Lua 5.x assigns array elements first in some cases)
|
||||||
* Equality comparisons call `__eq` metamethod even when objects are rawequal (which matches other metamethods like `<=` and facilitates NaN checking)
|
* Equality comparisons call `__eq` metamethod even when objects are rawequal (which matches other metamethods like `<=` and facilitates NaN checking)
|
||||||
|
* `function()` expressions may reuse a previosly created closure in certain scenarios (when all upvalues captured are the same) for efficiency, which changes object identity but doesn't change call semantics -- this is different from Lua 5.1 but similar to Lua 5.2/5.3
|
||||||
* `os.time` returns UTC timestamp when called with a table for consistency
|
* `os.time` returns UTC timestamp when called with a table for consistency
|
||||||
|
@ -24,7 +24,7 @@ stat = varlist '=' explist |
|
|||||||
'function' funcname funcbody |
|
'function' funcname funcbody |
|
||||||
'local' 'function' NAME funcbody |
|
'local' 'function' NAME funcbody |
|
||||||
'local' bindinglist ['=' explist] |
|
'local' bindinglist ['=' explist] |
|
||||||
['export'] type NAME ['<' GenericTypeList '>'] '=' Type
|
['export'] 'type' NAME ['<' GenericTypeList '>'] '=' Type
|
||||||
|
|
||||||
laststat = 'return' [explist] | 'break' | 'continue'
|
laststat = 'return' [explist] | 'break' | 'continue'
|
||||||
|
|
||||||
|
@ -21,21 +21,13 @@ local function tree_insert(tree, x)
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that future versions of Lua extend the Lua 5.1 syntax with the following features; Luau does support string literal extensions but does not support other features from this list:
|
Note that future versions of Lua extend the Lua 5.1 syntax with more features; Luau does support string literal extensions but does not support other 5.x additions; for details please refer to [compatibility section](compatibility).
|
||||||
|
|
||||||
- hexadecimal (`\x`), Unicode (`\u`) and `\z` escapes for string literals
|
|
||||||
- goto statements and labels
|
|
||||||
- bitwise operators
|
|
||||||
- floor division operator (`//`)
|
|
||||||
- `<toclose>` and `<const>` local attributes
|
|
||||||
|
|
||||||
> For details please refer to [compatibility section](compatibility).
|
|
||||||
|
|
||||||
The rest of this document documents additional syntax used in Luau.
|
The rest of this document documents additional syntax used in Luau.
|
||||||
|
|
||||||
## String literals
|
## String literals
|
||||||
|
|
||||||
As noted above, Luau implements support for hexadecimal (`\0x`), Unicode (`\u`) and `\z` escapes for string literals. This syntax follows [Lua 5.3 syntax](https://www.lua.org/manual/5.3/manual.html#3.1):
|
Luau implements support for hexadecimal (`\0x`), Unicode (`\u`) and `\z` escapes for string literals. This syntax follows [Lua 5.3 syntax](https://www.lua.org/manual/5.3/manual.html#3.1):
|
||||||
|
|
||||||
- `\xAB` inserts a character with the code 0xAB into the string
|
- `\xAB` inserts a character with the code 0xAB into the string
|
||||||
- `\u{ABC}` inserts a UTF8 byte sequence that encodes U+0ABC character into the string (note that braces are mandatory)
|
- `\u{ABC}` inserts a UTF8 byte sequence that encodes U+0ABC character into the string (note that braces are mandatory)
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
Add `coroutine.close` function from Lua 5.4 that takes a suspended coroutine and makes it "dead" (non-runnable).
|
Add `coroutine.close` function from Lua 5.4 that takes a suspended coroutine and makes it "dead" (non-runnable).
|
||||||
|
|
||||||
|
**Status**: Implemented
|
||||||
|
|
||||||
## Motivation
|
## Motivation
|
||||||
|
|
||||||
When implementing various higher level objects on top of coroutines, such as promises, it can be useful to cancel the coroutine execution externally - when the caller is not
|
When implementing various higher level objects on top of coroutines, such as promises, it can be useful to cancel the coroutine execution externally - when the caller is not
|
||||||
|
@ -32,6 +32,12 @@ Functions may also take generic type pack arguments for varargs, for instance:
|
|||||||
function compose<a...>(... : a...) -> (a...) return ... end
|
function compose<a...>(... : a...) -> (a...) return ... end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Generic type and type pack parameters can also be used in function types, for instance:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local id: <a>(a)->a = function(x) return x end
|
||||||
|
```
|
||||||
|
|
||||||
This change is *not* only syntax, as explicit type parameters need to be part of the semantics of types. For example, we can define a generic identity function
|
This change is *not* only syntax, as explicit type parameters need to be part of the semantics of types. For example, we can define a generic identity function
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
@ -86,6 +92,34 @@ Currently, Luau does not have explicit type binders, so `f` and `g` have the sam
|
|||||||
|
|
||||||
We propose supporting type parameters which can be instantiated with any type (jargon: Rank-N Types) but not type functions (jargon: Higher Kinded Types) or types with constraints (jargon: F-bounded polymorphism).
|
We propose supporting type parameters which can be instantiated with any type (jargon: Rank-N Types) but not type functions (jargon: Higher Kinded Types) or types with constraints (jargon: F-bounded polymorphism).
|
||||||
|
|
||||||
|
## Turbofish
|
||||||
|
|
||||||
|
Note that this RFC proposes a syntax for adding generic parameters to functions, but it does *not* propose syntax for adding generic arguments to function call site. For example, for `id` function you *can* write:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- generic type gets inferred as a number in all these cases
|
||||||
|
local x = id(4)
|
||||||
|
local x = id(y) :: number
|
||||||
|
local x: number = id(y)
|
||||||
|
```
|
||||||
|
|
||||||
|
but you can *not* write `id<number>(y)`.
|
||||||
|
|
||||||
|
This syntax is difficult to parse as it's ambiguous wrt grammar for comparison, and disambiguating it requires being able to parse types in expression context which makes parsing slow and complicated. It's also worth noting that today there are programs with this syntax that are grammatically correct (eg `id<string>('4')` parses as "compare variable `id` to variable `string`, and compare the result to string '4'"). The specific example with a single argument will always fail at runtime because booleans can't be compared with relational operators, but multi-argument cases such as `print(foo<number, string>(4))` can execute without errors in certain cases.
|
||||||
|
|
||||||
|
Note that in many cases the types can be inferred, whether through function arguments (`id(4)`) or through expected return type (`id(y) :: number`). It's also often possible to cast the function object to a given type, even though that can be unwieldy (`(id :: (number)->number)(y)`). Some languages don't have a way to specify the types at call site either, Swift being a prominent example. Thus it's not a given we need this feature in Luau.
|
||||||
|
|
||||||
|
If we ever want to implement this though, we can use a solution inspired by Rust's turbofish and require an extra token before `<`. Rust uses `::<` but that doesn't work in Luau because as part of this RFC, `id::<a>(a)->a` is a valid, if redundant, type ascription, so we need to choose a different prefix.
|
||||||
|
|
||||||
|
The following two variants are grammatically unambiguous in expression context in Luau, and are a better parallel for Rust's turbofish (in Rust, `::` is more similar to Luau's `:` or `.` than `::`, which in Rust is called `as`):
|
||||||
|
|
||||||
|
```lua
|
||||||
|
foo:<number, string>() -- require : before <; this is only valid in Luau in variable declaration context, so it's safe to use in expression context
|
||||||
|
foo.<number, string>() -- require . before <; this is currently never valid in Luau
|
||||||
|
```
|
||||||
|
|
||||||
|
This RFC doesn't propose using either of these options, but notes that either one of these options is possible to specify & implement in the future if we so desire.
|
||||||
|
|
||||||
## Drawbacks
|
## Drawbacks
|
||||||
|
|
||||||
This is a breaking change, in that examples like the unsound program above will no longer typecheck.
|
This is a breaking change, in that examples like the unsound program above will no longer typecheck.
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
The way `::` works today is really strange. The best solution we can come up with is to allow `::` to convert between any two related types.
|
The way `::` works today is really strange. The best solution we can come up with is to allow `::` to convert between any two related types.
|
||||||
|
|
||||||
|
**Status**: Implemented
|
||||||
|
|
||||||
## Motivation
|
## Motivation
|
||||||
|
|
||||||
Due to an accident of the implementation, the Luau `::` operator can only be used for downcasts and casts to `any`.
|
Due to an accident of the implementation, the Luau `::` operator can only be used for downcasts and casts to `any`.
|
||||||
|
Loading…
Reference in New Issue
Block a user