Fixed various spelling errors.

Co-authored-by: Josh Soref <jsoref@users.noreply.github.com>
This commit is contained in:
Josh Soref 2021-11-04 10:50:46 -04:00 committed by GitHub
parent 57a42c4cb9
commit 278e848cc2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 62 additions and 62 deletions

View file

@ -389,7 +389,7 @@ const std::string* getName(TypeId type);
// Checks whether a union contains all types of another union. // Checks whether a union contains all types of another union.
bool isSubset(const UnionTypeVar& super, const UnionTypeVar& sub); bool isSubset(const UnionTypeVar& super, const UnionTypeVar& sub);
// Checks if a type conains generic type binders // Checks if a type contains generic type binders
bool isGeneric(const TypeId ty); bool isGeneric(const TypeId ty);
// Checks if a type may be instantiated to one containing generic type binders // Checks if a type may be instantiated to one containing generic type binders

View file

@ -1461,7 +1461,7 @@ static AutocompleteResult autocomplete(const SourceModule& sourceModule, const M
result.erase(std::string(stringKey->value.data, stringKey->value.size)); result.erase(std::string(stringKey->value.data, stringKey->value.size));
} }
// If we know for sure that a key is being written, do not offer general epxression suggestions // If we know for sure that a key is being written, do not offer general expression suggestions
if (!key) if (!key)
autocompleteExpression(sourceModule, *module, typeChecker, typeArena, finder.ancestry, position, result); autocompleteExpression(sourceModule, *module, typeChecker, typeArena, finder.ancestry, position, result);

View file

@ -169,7 +169,7 @@ struct RequireTracer : AstVisitor
result.exprs[call] = fileResolver->concat(*rootName, v); result.exprs[call] = fileResolver->concat(*rootName, v);
// 'WaitForChild' can be used on modules that are not awailable at the typecheck time, but will be awailable at runtime // 'WaitForChild' can be used on modules that are not available at the typecheck time, but will be available at runtime
// If we fail to find such module, we will not report an UnknownRequire error // If we fail to find such module, we will not report an UnknownRequire error
if (FFlag::LuauTraceRequireLookupChild && indexName->index == "WaitForChild") if (FFlag::LuauTraceRequireLookupChild && indexName->index == "WaitForChild")
result.optional[call] = true; result.optional[call] = true;

View file

@ -412,7 +412,7 @@ void TypeChecker::checkBlock(const ScopePtr& scope, const AstStatBlock& block)
// ``` // ```
// These both call each other, so `f` will be ordered before `g`, so the call to `g` // These both call each other, so `f` will be ordered before `g`, so the call to `g`
// is typechecked before `g` has had its body checked. For this reason, there's three // is typechecked before `g` has had its body checked. For this reason, there's three
// types for each functuion: before its body is checked, during checking its body, // types for each function: before its body is checked, during checking its body,
// and after its body is checked. // and after its body is checked.
// //
// We currently treat the before-type and the during-type as the same, // We currently treat the before-type and the during-type as the same,
@ -1076,7 +1076,7 @@ void TypeChecker::check(const ScopePtr& scope, TypeId ty, const ScopePtr& funSco
checkFunctionBody(funScope, ty, *function.func); checkFunctionBody(funScope, ty, *function.func);
// If in nonstrict mode and allowing redefinition of global function, restore the previous definition type // If in nonstrict mode and allowing redefinition of global function, restore the previous definition type
// in case this function has a differing signature. The signature discrepency will be caught in checkBlock. // in case this function has a differing signature. The signature discrepancy will be caught in checkBlock.
if (previouslyDefined) if (previouslyDefined)
globalBindings[name] = oldBinding; globalBindings[name] = oldBinding;
else else
@ -3150,7 +3150,7 @@ void TypeChecker::checkArgumentList(
const ScopePtr& scope, Unifier& state, TypePackId argPack, TypePackId paramPack, const std::vector<Location>& argLocations) const ScopePtr& scope, Unifier& state, TypePackId argPack, TypePackId paramPack, const std::vector<Location>& argLocations)
{ {
/* Important terminology refresher: /* Important terminology refresher:
* A function requires paramaters. * A function requires parameters.
* To call a function, you supply arguments. * To call a function, you supply arguments.
*/ */
TypePackIterator argIter = begin(argPack); TypePackIterator argIter = begin(argPack);

View file

@ -1025,7 +1025,7 @@ void Unifier::tryUnifySealedTables(TypeId left, TypeId right, bool isIntersectio
// If the superTy/left is an immediate part of an intersection type, do not do extra-property check. // If the superTy/left is an immediate part of an intersection type, do not do extra-property check.
// Otherwise, we would falsely generate an extra-property-error for 's' in this code: // Otherwise, we would falsely generate an extra-property-error for 's' in this code:
// local a: {n: number} & {s: string} = {n=1, s=""} // local a: {n: number} & {s: string} = {n=1, s=""}
// When checking agaist the table '{n: number}'. // When checking against the table '{n: number}'.
if (!isIntersection && lt->state != TableState::Unsealed && !lt->indexer) if (!isIntersection && lt->state != TableState::Unsealed && !lt->indexer)
{ {
// Check for extra properties in the subTy // Check for extra properties in the subTy

View file

@ -1535,7 +1535,7 @@ AstType* Parser::parseSimpleTypeAnnotation()
{ {
Location location = lexer.current().location; Location location = lexer.current().location;
// For a missing type annoation, capture 'space' between last token and the next one // For a missing type annotation, capture 'space' between last token and the next one
location = Location(lexer.previousLocation().end, lexer.current().location.begin); location = Location(lexer.previousLocation().end, lexer.current().location.begin);
return reportTypeAnnotationError(location, {}, /*isMissing*/ true, "Expected type, got %s", lexer.current().toString().c_str()); return reportTypeAnnotationError(location, {}, /*isMissing*/ true, "Expected type, got %s", lexer.current().toString().c_str());

View file

@ -208,14 +208,14 @@ enum LuauOpcode
LOP_MODK, LOP_MODK,
LOP_POWK, LOP_POWK,
// AND, OR: perform `and` or `or` operation (selecting first or second register based on whether the first one is truthful) and put the result into target register // AND, OR: perform `and` or `or` operation (selecting first or second register based on whether the first one is truthy) and put the result into target register
// A: target register // A: target register
// B: source register 1 // B: source register 1
// C: source register 2 // C: source register 2
LOP_AND, LOP_AND,
LOP_OR, LOP_OR,
// ANDK, ORK: perform `and` or `or` operation (selecting source register or constant based on whether the source register is truthful) and put the result into target register // ANDK, ORK: perform `and` or `or` operation (selecting source register or constant based on whether the source register is truthy) and put the result into target register
// A: target register // A: target register
// B: source register // B: source register
// C: constant table index (0..255) // C: constant table index (0..255)

View file

@ -712,9 +712,9 @@ struct Compiler
} }
// compile expr to target temp register // compile expr to target temp register
// if the expr (or not expr if onlyTruth is false) is truthful, jump via skipJump // if the expr (or not expr if onlyTruth is false) is truthy, jump via skipJump
// if the expr (or not expr if onlyTruth is false) is falseful, fall through (target isn't guaranteed to be updated in this case) // if the expr (or not expr if onlyTruth is false) is falsy, fall through (target isn't guaranteed to be updated in this case)
// if target is omitted, then the jump behavior is the same - skipJump or fallthrough depending on the truthfulness of the expression // if target is omitted, then the jump behavior is the same - skipJump or fallthrough depending on the truthiness of the expression
void compileConditionValue(AstExpr* node, const uint8_t* target, std::vector<size_t>& skipJump, bool onlyTruth) void compileConditionValue(AstExpr* node, const uint8_t* target, std::vector<size_t>& skipJump, bool onlyTruth)
{ {
// Optimization: we don't need to compute constant values // Optimization: we don't need to compute constant values
@ -722,7 +722,7 @@ struct Compiler
if (cv && cv->type != Constant::Type_Unknown) if (cv && cv->type != Constant::Type_Unknown)
{ {
// note that we only need to compute the value if it's truthful; otherwise we cal fall through // note that we only need to compute the value if it's truthy; otherwise we cal fall through
if (cv->isTruthful() == onlyTruth) if (cv->isTruthful() == onlyTruth)
{ {
if (target) if (target)
@ -741,7 +741,7 @@ struct Compiler
case AstExprBinary::And: case AstExprBinary::And:
case AstExprBinary::Or: case AstExprBinary::Or:
{ {
// disambiguation: there's 4 cases (we only need truthful or falseful results based on onlyTruth) // disambiguation: there's 4 cases (we only need truthy or falsy results based on onlyTruth)
// onlyTruth = 1: a and b transforms to a ? b : dontcare // onlyTruth = 1: a and b transforms to a ? b : dontcare
// onlyTruth = 1: a or b transforms to a ? a : a // onlyTruth = 1: a or b transforms to a ? a : a
// onlyTruth = 0: a and b transforms to !a ? a : b // onlyTruth = 0: a and b transforms to !a ? a : b
@ -785,8 +785,8 @@ struct Compiler
if (target) if (target)
{ {
// since target is a temp register, we'll initialize it to 1, and then jump if the comparison is true // since target is a temp register, we'll initialize it to 1, and then jump if the comparison is true
// if the comparison is false, we'll fallthrough and target will still be 1 but target has unspecified value for falseful results // if the comparison is false, we'll fallthrough and target will still be 1 but target has unspecified value for falsy results
// when we only care about falseful values instead of truthful values, the process is the same but with flipped conditionals // when we only care about falsy values instead of truthy values, the process is the same but with flipped conditionals
bytecode.emitABC(LOP_LOADB, *target, onlyTruth ? 1 : 0, 0); bytecode.emitABC(LOP_LOADB, *target, onlyTruth ? 1 : 0, 0);
} }

View file

@ -45,7 +45,7 @@ To gain advantage of many performance improvements it's highly recommended to us
# Testing # Testing
Luau has an internal test suite; in CMake builds it is split into two targets, `Luau.UnitTest` (for bytecode compiler and type checker/linter tests) and `Luau.Conformance` (for VM tests). The unit tests are written in C++, whereas the conformance tests are largerly written in Luau (see `tests/conformance`). Luau has an internal test suite; in CMake builds it is split into two targets, `Luau.UnitTest` (for bytecode compiler and type checker/linter tests) and `Luau.Conformance` (for VM tests). The unit tests are written in C++, whereas the conformance tests are largely written in Luau (see `tests/conformance`).
Makefile builds combine both into a single target and can be ran via `make test`. Makefile builds combine both into a single target and can be ran via `make test`.

View file

@ -76,7 +76,7 @@ struct luaL_Buffer
char buffer[LUA_BUFFERSIZE]; char buffer[LUA_BUFFERSIZE];
}; };
// when internal buffer storage is exhaused, a mutable string value 'storage' will be placed on the stack // when internal buffer storage is exhausted, a mutable string value 'storage' will be placed on the stack
// in general, functions expect the mutable string buffer to be placed on top of the stack (top-1) // in general, functions expect the mutable string buffer to be placed on top of the stack (top-1)
// with the exception of luaL_addvalue that expects the value at the top and string buffer further away (top-2) // with the exception of luaL_addvalue that expects the value at the top and string buffer further away (top-2)
// functions that accept a 'boxloc' support string buffer placement at any location in the stack // functions that accept a 'boxloc' support string buffer placement at any location in the stack

View file

@ -313,7 +313,7 @@ static size_t getnextbuffersize(lua_State* L, size_t currentsize, size_t desired
{ {
size_t newsize = currentsize + currentsize / 2; size_t newsize = currentsize + currentsize / 2;
// check for size oveflow // check for size overflow
if (SIZE_MAX - desiredsize < currentsize) if (SIZE_MAX - desiredsize < currentsize)
luaL_error(L, "buffer too large"); luaL_error(L, "buffer too large");

View file

@ -25,7 +25,7 @@ static int costatus(lua_State* L, lua_State* co)
return CO_SUS; return CO_SUS;
if (co->status == LUA_BREAK) if (co->status == LUA_BREAK)
return CO_NOR; return CO_NOR;
if (co->status != 0) /* some error occured */ if (co->status != 0) /* some error occurred */
return CO_DEAD; return CO_DEAD;
if (co->ci != co->base_ci) /* does it have frames? */ if (co->ci != co->base_ci) /* does it have frames? */
return CO_NOR; return CO_NOR;

View file

@ -532,7 +532,7 @@ int luaD_pcall(lua_State* L, Pfunc func, void* u, ptrdiff_t old_top, ptrdiff_t e
status = LUA_ERRERR; status = LUA_ERRERR;
} }
// an error occured, check if we have a protected error callback // an error occurred, check if we have a protected error callback
if (L->global->cb.debugprotectederror) if (L->global->cb.debugprotectederror)
{ {
L->global->cb.debugprotectederror(L); L->global->cb.debugprotectederror(L);

View file

@ -37,7 +37,7 @@
/* results from luaD_precall */ /* results from luaD_precall */
#define PCRLUA 0 /* initiated a call to a Lua function */ #define PCRLUA 0 /* initiated a call to a Lua function */
#define PCRC 1 /* did a call to a C function */ #define PCRC 1 /* did a call to a C function */
#define PCRYIELD 2 /* C funtion yielded */ #define PCRYIELD 2 /* C function yielded */
/* type of protected functions, to be ran by `runprotected' */ /* type of protected functions, to be ran by `runprotected' */
typedef void (*Pfunc)(lua_State* L, void* ud); typedef void (*Pfunc)(lua_State* L, void* ud);

View file

@ -76,7 +76,7 @@ UpVal* luaF_findupval(lua_State* L, StkId level)
if (p->v == level) if (p->v == level)
{ /* found a corresponding upvalue? */ { /* found a corresponding upvalue? */
if (isdead(g, obj2gco(p))) /* is it dead? */ if (isdead(g, obj2gco(p))) /* is it dead? */
changewhite(obj2gco(p)); /* ressurect it */ changewhite(obj2gco(p)); /* resurrect it */
return p; return p;
} }
pp = &p->next; pp = &p->next;

View file

@ -884,7 +884,7 @@ void luaC_step(lua_State* L, bool assist)
g->gcstats.currcycle.explicitwork += lim; g->gcstats.currcycle.explicitwork += lim;
int lastgcstate = g->gcstate; int lastgcstate = g->gcstate;
double lastttimestamp = lua_clock(); double lasttimestamp = lua_clock();
// always perform at least one single step // always perform at least one single step
do do
@ -899,14 +899,14 @@ void luaC_step(lua_State* L, bool assist)
double now = lua_clock(); double now = lua_clock();
recordGcStateTime(g, lastgcstate, now - lastttimestamp, assist); recordGcStateTime(g, lastgcstate, now - lasttimestamp, assist);
lastttimestamp = now; lasttimestamp = now;
lastgcstate = g->gcstate; lastgcstate = g->gcstate;
} }
} while (lim > 0 && g->gcstate != GCSpause); } while (lim > 0 && g->gcstate != GCSpause);
recordGcStateTime(g, lastgcstate, lua_clock() - lastttimestamp, assist); recordGcStateTime(g, lastgcstate, lua_clock() - lasttimestamp, assist);
// at the end of the last cycle // at the end of the last cycle
if (g->gcstate == GCSpause) if (g->gcstate == GCSpause)

View file

@ -28,7 +28,7 @@ LUAU_FASTFLAG(LuauGcFullSkipInactiveThreads)
#define keepinvariant(g) ((g)->gcstate == GCSpropagate || (g)->gcstate == GCSpropagateagain) #define keepinvariant(g) ((g)->gcstate == GCSpropagate || (g)->gcstate == GCSpropagateagain)
/* /*
** some userful bit tricks ** some useful bit tricks
*/ */
#define resetbits(x, m) ((x) &= cast_to(uint8_t, ~(m))) #define resetbits(x, m) ((x) &= cast_to(uint8_t, ~(m)))
#define setbits(x, m) ((x) |= (m)) #define setbits(x, m) ((x) |= (m))

View file

@ -21,7 +21,7 @@ local bench = script and require(script.Parent.bench_support) or require("bench_
-- This implementation of the DeltaBlue benchmark is derived -- This implementation of the DeltaBlue benchmark is derived
-- from the Smalltalk implementation by John Maloney and Mario -- from the Smalltalk implementation by John Maloney and Mario
-- Wolczko. Some parts have been translated directly, whereas -- Wolczko. Some parts have been translated directly, whereas
-- others have been modified more aggresively to make it feel -- others have been modified more aggressively to make it feel
-- more like a JavaScript program. -- more like a JavaScript program.
@ -222,7 +222,7 @@ end
-- --
-- Normal constraints are not input constraints. An input constraint -- Normal constraints are not input constraints. An input constraint
-- is one that depends on external state, such as the mouse, the -- is one that depends on external state, such as the mouse, the
-- keybord, a clock, or some arbitraty piece of imperative code. -- keyboard, a clock, or some arbitrary piece of imperative code.
-- --
function Constraint:isInput () function Constraint:isInput ()
return false return false
@ -614,7 +614,7 @@ end
-- --
-- Attempt to satisfy the given constraint and, if successful, -- Attempt to satisfy the given constraint and, if successful,
-- incrementally update the dataflow graph. Details: If satifying -- incrementally update the dataflow graph. Details: If satisfying
-- the constraint is successful, it may override a weaker constraint -- the constraint is successful, it may override a weaker constraint
-- on its output. The algorithm attempts to resatisfy that -- on its output. The algorithm attempts to resatisfy that
-- constraint using some other method. This process is repeated -- constraint using some other method. This process is repeated
@ -837,7 +837,7 @@ end
-- In case 1, the added constraint is stronger than the stay -- In case 1, the added constraint is stronger than the stay
-- constraint and values must propagate down the entire length of the -- constraint and values must propagate down the entire length of the
-- chain. In case 2, the added constraint is weaker than the stay -- chain. In case 2, the added constraint is weaker than the stay
-- constraint so it cannot be accomodated. The cost in this case is, -- constraint so it cannot be accommodated. The cost in this case is,
-- of course, very low. Typical situations lie somewhere between these -- of course, very low. Typical situations lie somewhere between these
-- two extremes. -- two extremes.
-- --

View file

@ -30,7 +30,7 @@
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- Modificatin to be compatible with Lua 5.3 -- Modification to be compatible with Lua 5.3
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local bench = script and require(script.Parent.bench_support) or require("bench_support") local bench = script and require(script.Parent.bench_support) or require("bench_support")

View file

@ -18,7 +18,7 @@ While most library functions are provided as part of a library like `table`, a f
function assert<T>(value: T, message: string?): T function assert<T>(value: T, message: string?): T
``` ```
`assert` checks if the value is truthful; if it's not (which means it's `false` or `nil`), it raises an error. The error message can be customized with an optional parameter. `assert` checks if the value is truthy; if it's not (which means it's `false` or `nil`), it raises an error. The error message can be customized with an optional parameter.
Upon success the function returns the `condition` argument. Upon success the function returns the `condition` argument.
``` ```
@ -146,7 +146,7 @@ Returns the triple (generator, state, nil) that can be used to traverse the tabl
function pcall(f: function, args: ...any): (boolean, ...any) function pcall(f: function, args: ...any): (boolean, ...any)
``` ```
Calls function `f` with parameters `args`. If the function suceeds, returns `true` followed by all return values of `f`. If the function raises an error, returns `false` followed by the error object. Calls function `f` with parameters `args`. If the function succeeds, returns `true` followed by all return values of `f`. If the function raises an error, returns `false` followed by the error object.
Note that `f` can yield, which results in the entire coroutine yielding as well. Note that `f` can yield, which results in the entire coroutine yielding as well.
``` ```
@ -205,7 +205,7 @@ Rounds `n` upwards to the next integer boundary.
function math.cosh(n: number): number function math.cosh(n: number): number
``` ```
Returns the hyberbolic cosine of `n`. Returns the hyperbolic cosine of `n`.
``` ```
function math.cos(n: number): number function math.cos(n: number): number
@ -792,4 +792,4 @@ function debug.traceback(co: thread, msg: string?, level: number?): string
function debug.traceback(msg: string?, level: number?): string function debug.traceback(msg: string?, level: number?): string
``` ```
Produces a stringifed callstack of the given thread, or the current thread, starting with level `level`. If `msg` is specified, then the resulting callstack includes the string before the callstack output, separated with a newline. The format of the callstack is human-readable and subject to change. Produces a stringified callstack of the given thread, or the current thread, starting with level `level`. If `msg` is specified, then the resulting callstack includes the string before the callstack output, separated with a newline. The format of the callstack is human-readable and subject to change.

View file

@ -88,7 +88,7 @@ The mechanism works by directly invoking a highly specialized and optimized impl
As a result, builtin calls are very fast in Luau - they are still slightly slower than core instructions such as arithmetic operations, but only slightly so. The set of fastcall builtins is slowly expanding over time and as of this writing contains `assert`, `type`, `typeof`, `rawget`/`rawset`/`rawequal`, all functions from `math` and `bit32`, and some functions from `string` and `table` library. As a result, builtin calls are very fast in Luau - they are still slightly slower than core instructions such as arithmetic operations, but only slightly so. The set of fastcall builtins is slowly expanding over time and as of this writing contains `assert`, `type`, `typeof`, `rawget`/`rawset`/`rawequal`, all functions from `math` and `bit32`, and some functions from `string` and `table` library.
> Note: The partial specialization mechanism is cute in that for `assert`, it only specializes on truthful conditions; hopefully performance of `assert(false)` isn't crucial for most code! > Note: The partial specialization mechanism is cute in that for `assert`, it only specializes on truthy conditions; hopefully performance of `assert(false)` isn't crucial for most code!
## Optimized table iteration ## Optimized table iteration

View file

@ -14,7 +14,7 @@ Today Luau provides only one method to get the callstack, `debug.traceback`. Thi
There are a few cases where this can be inconvenient: There are a few cases where this can be inconvenient:
- Sometimes it is useful to pass the resulting call stack to some system expecting a structured input, e.g. for crash aggreggation - Sometimes it is useful to pass the resulting call stack to some system expecting a structured input, e.g. for crash aggregation
- Sometimes it is useful to use the information about the caller for logging or filtering purposes; in these cases using just the script name can be useful, and getting script name out of the traceback is slow and imprecise - Sometimes it is useful to use the information about the caller for logging or filtering purposes; in these cases using just the script name can be useful, and getting script name out of the traceback is slow and imprecise
Additionally, in some cases instead of getting the information (such as script or function name) from the callstack, it can be useful to get it from a function object for diagnostic purposes. For example, maybe you want to call a callback and if it doesn't return expected results, display a user-friendly error message that contains the function name & script location - these aren't possible today at all. Additionally, in some cases instead of getting the information (such as script or function name) from the callstack, it can be useful to get it from a function object for diagnostic purposes. For example, maybe you want to call a callback and if it doesn't return expected results, display a user-friendly error message that contains the function name & script location - these aren't possible today at all.

View file

@ -44,7 +44,7 @@ To limit the use of `table.freeze` to cases when table contents can be freely ma
Exposing the internal "readonly" feature may have an impact on interoperability between scripts - for example, it becomes possible to freeze some tables that scripts may be expecting to have write access to from other scripts. Since we don't provide a way to unfreeze tables and freezing a table with a locked metatable fails, in theory the impact should not be any worse than allowing to change a metatable, but the full extents are unclear. Exposing the internal "readonly" feature may have an impact on interoperability between scripts - for example, it becomes possible to freeze some tables that scripts may be expecting to have write access to from other scripts. Since we don't provide a way to unfreeze tables and freezing a table with a locked metatable fails, in theory the impact should not be any worse than allowing to change a metatable, but the full extents are unclear.
There may be existing code in the VM that allows changing frozen tables in ways that are benign to the current sanboxing code, but expose a "gap" in the implementation that becomes significant with this feature; thus we would need to audit all table writes when implementing this. There may be existing code in the VM that allows changing frozen tables in ways that are benign to the current sandboxing code, but expose a "gap" in the implementation that becomes significant with this feature; thus we would need to audit all table writes when implementing this.
## Alternatives ## Alternatives

View file

@ -56,7 +56,7 @@ end
These rules are simple to implement. In any Lua parser there is already a point where you have to disambiguate an identifier that starts an assignment statement (`foo = 5`) from an identifier that starts a function call (`foo(5)`). It's one of the few, if not the only, place in the Lua grammar where single token lookahead is not sufficient to parse Lua, because you could have `foo.bar(5)` or `foo.bar=5` or `foo.bar(5)[6] = 7`. These rules are simple to implement. In any Lua parser there is already a point where you have to disambiguate an identifier that starts an assignment statement (`foo = 5`) from an identifier that starts a function call (`foo(5)`). It's one of the few, if not the only, place in the Lua grammar where single token lookahead is not sufficient to parse Lua, because you could have `foo.bar(5)` or `foo.bar=5` or `foo.bar(5)[6] = 7`.
Because of this, we need to parse the entire left hand side of an assignment statement (primaryexpr in Lua's BNF) and then check if it was a function call; if not, we'd expect it to be an assignment statement. Because of this, we need to parse the entire left hand side of an assignment statement (primaryexp in Lua's BNF) and then check if it was a function call; if not, we'd expect it to be an assignment statement.
Alternatively in this specific case we could parse "continue", parse the next token, and if it's one of the exclusion list above, roll the parser state back and re-parse the non-continue statement. Our lexer currently doesn't support rollbacks but it's also an easy strategy that other implementations might employ for `continue` specifically. Alternatively in this specific case we could parse "continue", parse the next token, and if it's one of the exclusion list above, roll the parser state back and re-parse the non-continue statement. Our lexer currently doesn't support rollbacks but it's also an easy strategy that other implementations might employ for `continue` specifically.

View file

@ -12,7 +12,7 @@ Introduce a form of ternary conditional using `if cond then value else alternati
Luau does not have a first-class ternary operator; when a ternary operator is needed, it is usually emulated with `and/or` expression, such as `cond and value or alternative`. Luau does not have a first-class ternary operator; when a ternary operator is needed, it is usually emulated with `and/or` expression, such as `cond and value or alternative`.
This expression evaluates to `value` if `cond` and `value` are truthful, and `alternative` otherwise. In particular it means that when `value` is `false` or `nil`, the result of the entire expression is `alternative` even when `cond` is truthful - which doesn't match the expected ternary logic and is a frequent source of subtle errors. This expression evaluates to `value` if `cond` and `value` are truthy, and `alternative` otherwise. In particular it means that when `value` is `false` or `nil`, the result of the entire expression is `alternative` even when `cond` is truthy - which doesn't match the expected ternary logic and is a frequent source of subtle errors.
Instead of `and/or`, `if/else` statement can be used but since that requires a separate mutable variable, this option isn't ergonomic. An immediately invoked function expression is also unergonomic and results in performance issues at runtime. Instead of `and/or`, `if/else` statement can be used but since that requires a separate mutable variable, this option isn't ergonomic. An immediately invoked function expression is also unergonomic and results in performance issues at runtime.
@ -22,7 +22,7 @@ To solve these problems, we propose introducing a first-class ternary conditiona
Concretely, the `if-then-else` expression must match `if <expr> then <expr> else <expr>`; it can also contain an arbitrary number of `elseif` clauses, like `if <expr> then <expr> elseif <expr> then <expr> else <expr>`. Note that in either case, `else` is mandatory. Concretely, the `if-then-else` expression must match `if <expr> then <expr> else <expr>`; it can also contain an arbitrary number of `elseif` clauses, like `if <expr> then <expr> elseif <expr> then <expr> else <expr>`. Note that in either case, `else` is mandatory.
The result of the expression is the then-expression when condition is truthful (not `nil` or `false`) and else-expression otherwise. Only one of the two possible resulting expressions is evaluated. The result of the expression is the then-expression when condition is truthy (not `nil` or `false`) and else-expression otherwise. Only one of the two possible resulting expressions is evaluated.
Example: Example:

View file

@ -359,7 +359,7 @@ TEST_CASE_FIXTURE(Fixture, "table_insert_correctly_infers_type_of_array_2_args_o
CHECK_EQ(typeChecker.stringType, requireType("s")); CHECK_EQ(typeChecker.stringType, requireType("s"));
} }
TEST_CASE_FIXTURE(Fixture, "table_insert_corrrectly_infers_type_of_array_3_args_overload") TEST_CASE_FIXTURE(Fixture, "table_insert_correctly_infers_type_of_array_3_args_overload")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = {} local t = {}

View file

@ -14,7 +14,7 @@ using namespace Luau;
TEST_SUITE_BEGIN("ProvisionalTests"); TEST_SUITE_BEGIN("ProvisionalTests");
// These tests check for behavior that differes from the final behavior we'd // These tests check for behavior that differs from the final behavior we'd
// like to have. They serve to document the current state of the typechecker. // like to have. They serve to document the current state of the typechecker.
// When making future improvements, its very likely these tests will break and // When making future improvements, its very likely these tests will break and
// will need to be replaced. // will need to be replaced.

View file

@ -405,7 +405,7 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_error_on_factory_not_returning_the_right
for p in primes2() do print(p) end -- mismatch in argument types, prime_iter takes {}, number, we are given {}, string for p in primes2() do print(p) end -- mismatch in argument types, prime_iter takes {}, number, we are given {}, string
for p in primes3() do print(p) end -- no errror for p in primes3() do print(p) end -- no error
)"); )");
LUAU_REQUIRE_ERROR_COUNT(2, result); LUAU_REQUIRE_ERROR_COUNT(2, result);
@ -2582,7 +2582,7 @@ TEST_CASE_FIXTURE(Fixture, "toposort_doesnt_break_mutual_recursion")
--!strict --!strict
local x = nil local x = nil
function f() g() end function f() g() end
-- make sure print(x) doen't get toposorted here, breaking the mutual block -- make sure print(x) doesn't get toposorted here, breaking the mutual block
function g() x = f end function g() x = f end
print(x) print(x)
)"); )");
@ -3062,7 +3062,7 @@ TEST_CASE_FIXTURE(Fixture, "correctly_scope_locals_while")
CHECK_EQ(us->name, "a"); CHECK_EQ(us->name, "a");
} }
TEST_CASE_FIXTURE(Fixture, "ipairs_produces_integral_indeces") TEST_CASE_FIXTURE(Fixture, "ipairs_produces_integral_indices")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local key local key
@ -4885,7 +4885,7 @@ f(function(a) return a.x + a.y end)
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
// An optional funciton is accepted, but since we already provide a function, nil can be ignored // An optional function is accepted, but since we already provide a function, nil can be ignored
result = check(R"( result = check(R"(
type Table = { x: number, y: number } type Table = { x: number, y: number }
local function f(a: ((Table) -> number)?) if a then return a({x = 1, y = 2}) else return 0 end end local function f(a: ((Table) -> number)?) if a then return a({x = 1, y = 2}) else return 0 end end
@ -4913,7 +4913,7 @@ f(function(a: number, b, c) return c and a + b or b - a end)
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
// Anonymous function has a varyadic pack // Anonymous function has a variadic pack
result = check(R"( result = check(R"(
type Table = { x: number, y: number } type Table = { x: number, y: number }
local function f(a: (Table) -> number) return a({x = 1, y = 2}) end local function f(a: (Table) -> number) return a({x = 1, y = 2}) end
@ -4932,7 +4932,7 @@ f(function(a, b, c, ...) return a + b end)
LUAU_REQUIRE_ERRORS(result); LUAU_REQUIRE_ERRORS(result);
CHECK_EQ("Type '(number, number, a) -> number' could not be converted into '(number, number) -> number'", toString(result.errors[0])); CHECK_EQ("Type '(number, number, a) -> number' could not be converted into '(number, number) -> number'", toString(result.errors[0]));
// Infer from varyadic packs into elements // Infer from variadic packs into elements
result = check(R"( result = check(R"(
function f(a: (...number) -> number) return a(1, 2) end function f(a: (...number) -> number) return a(1, 2) end
f(function(a, b) return a + b end) f(function(a, b) return a + b end)
@ -4940,7 +4940,7 @@ f(function(a, b) return a + b end)
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
// Infer from varyadic packs into varyadic packs // Infer from variadic packs into variadic packs
result = check(R"( result = check(R"(
type Table = { x: number, y: number } type Table = { x: number, y: number }
function f(a: (...Table) -> number) return a({x = 1, y = 2}, {x = 3, y = 4}) end function f(a: (...Table) -> number) return a({x = 1, y = 2}, {x = 3, y = 4}) end

View file

@ -52,7 +52,7 @@ TEST_CASE_FIXTURE(Fixture, "allow_more_specific_assign")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "disallow_less_specifc_assign") TEST_CASE_FIXTURE(Fixture, "disallow_less_specific_assign")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a:number = 10 local a:number = 10
@ -63,7 +63,7 @@ TEST_CASE_FIXTURE(Fixture, "disallow_less_specifc_assign")
LUAU_REQUIRE_ERROR_COUNT(1, result); LUAU_REQUIRE_ERROR_COUNT(1, result);
} }
TEST_CASE_FIXTURE(Fixture, "disallow_less_specifc_assign2") TEST_CASE_FIXTURE(Fixture, "disallow_less_specific_assign2")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a:number? = 10 local a:number? = 10

View file

@ -319,7 +319,7 @@ end
assert(a == 5^4) assert(a == 5^4)
-- access to locals of collected corroutines -- access to locals of collected coroutines
local C = {}; setmetatable(C, {__mode = "kv"}) local C = {}; setmetatable(C, {__mode = "kv"})
local x = coroutine.wrap (function () local x = coroutine.wrap (function ()
local a = 10 local a = 10

View file

@ -185,7 +185,7 @@ end
assert(a == 5^4) assert(a == 5^4)
-- access to locals of collected corroutines -- access to locals of collected coroutines
local C = {}; setmetatable(C, {__mode = "kv"}) local C = {}; setmetatable(C, {__mode = "kv"})
local x = coroutine.wrap (function () local x = coroutine.wrap (function ()
local a = 10 local a = 10

View file

@ -277,7 +277,7 @@ do
assert(getmetatable(o) == tt) assert(getmetatable(o) == tt)
-- create new objects during GC -- create new objects during GC
local a = 'xuxu'..(10+3)..'joao', {} local a = 'xuxu'..(10+3)..'joao', {}
___Glob = o -- ressurect object! ___Glob = o -- resurrect object!
newproxy(o) -- creates a new one with same metatable newproxy(o) -- creates a new one with same metatable
print(">>> closing state " .. "<<<\n") print(">>> closing state " .. "<<<\n")
end end

View file

@ -117,7 +117,7 @@ if rawget(_G, "querytab") then
local t = querytab(a) local t = querytab(a)
for k,_ in pairs(a) do a[k] = nil end for k,_ in pairs(a) do a[k] = nil end
collectgarbage() -- restore GC and collect dead fiels in `a' collectgarbage() -- restore GC and collect dead fields in `a'
for i=0,t-1 do for i=0,t-1 do
local k = querytab(a, i) local k = querytab(a, i)
assert(k == nil or type(k) == 'number' or k == 'alo') assert(k == nil or type(k) == 'number' or k == 'alo')

View file

@ -172,7 +172,7 @@ end
a = nil a = nil
-- testing implicit convertions -- testing implicit conversions
local a,b = '10', '20' local a,b = '10', '20'
assert(a*b == 200 and a+b == 30 and a-b == -10 and a/b == 0.5 and -b == -20) assert(a*b == 200 and a+b == 30 and a-b == -10 and a/b == 0.5 and -b == -20)

View file

@ -21,9 +21,9 @@ a,b = string.find('alo', '')
assert(a == 1 and b == 0) assert(a == 1 and b == 0)
a,b = string.find('a\0o a\0o a\0o', 'a', 1) -- first position a,b = string.find('a\0o a\0o a\0o', 'a', 1) -- first position
assert(a == 1 and b == 1) assert(a == 1 and b == 1)
a,b = string.find('a\0o a\0o a\0o', 'a\0o', 2) -- starts in the midle a,b = string.find('a\0o a\0o a\0o', 'a\0o', 2) -- starts in the middle
assert(a == 5 and b == 7) assert(a == 5 and b == 7)
a,b = string.find('a\0o a\0o a\0o', 'a\0o', 9) -- starts in the midle a,b = string.find('a\0o a\0o a\0o', 'a\0o', 9) -- starts in the middle
assert(a == 9 and b == 11) assert(a == 9 and b == 11)
a,b = string.find('a\0a\0a\0a\0\0ab', '\0ab', 2); -- finds at the end a,b = string.find('a\0a\0a\0a\0\0ab', '\0ab', 2); -- finds at the end
assert(a == 9 and b == 11); assert(a == 9 and b == 11);