Sync to upstream/release/537 (#607)
This commit is contained in:
parent
a824b05c9e
commit
b1cfaf5305
|
@ -2,12 +2,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
|
||||
class AstNode;
|
||||
struct Comment;
|
||||
|
||||
std::string toJson(AstNode* node);
|
||||
std::string toJson(AstNode* node, const std::vector<Comment>& commentLocations);
|
||||
|
||||
} // namespace Luau
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
LUAU_FASTINT(LuauVisitRecursionLimit)
|
||||
LUAU_FASTFLAG(LuauNormalizeFlagIsConservative)
|
||||
LUAU_FASTFLAG(LuauCompleteVisitor);
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
|
@ -129,11 +130,11 @@ struct GenericTypeVarVisitor
|
|||
{
|
||||
return visit(ty);
|
||||
}
|
||||
virtual bool visit(TypeId ty, const UnknownTypeVar& atv)
|
||||
virtual bool visit(TypeId ty, const UnknownTypeVar& utv)
|
||||
{
|
||||
return visit(ty);
|
||||
}
|
||||
virtual bool visit(TypeId ty, const NeverTypeVar& atv)
|
||||
virtual bool visit(TypeId ty, const NeverTypeVar& ntv)
|
||||
{
|
||||
return visit(ty);
|
||||
}
|
||||
|
@ -145,6 +146,14 @@ struct GenericTypeVarVisitor
|
|||
{
|
||||
return visit(ty);
|
||||
}
|
||||
virtual bool visit(TypeId ty, const BlockedTypeVar& btv)
|
||||
{
|
||||
return visit(ty);
|
||||
}
|
||||
virtual bool visit(TypeId ty, const SingletonTypeVar& stv)
|
||||
{
|
||||
return visit(ty);
|
||||
}
|
||||
|
||||
virtual bool visit(TypePackId tp)
|
||||
{
|
||||
|
@ -190,16 +199,12 @@ struct GenericTypeVarVisitor
|
|||
if (visit(ty, *btv))
|
||||
traverse(btv->boundTo);
|
||||
}
|
||||
|
||||
else if (auto ftv = get<FreeTypeVar>(ty))
|
||||
visit(ty, *ftv);
|
||||
|
||||
else if (auto gtv = get<GenericTypeVar>(ty))
|
||||
visit(ty, *gtv);
|
||||
|
||||
else if (auto etv = get<ErrorTypeVar>(ty))
|
||||
visit(ty, *etv);
|
||||
|
||||
else if (auto ctv = get<ConstrainedTypeVar>(ty))
|
||||
{
|
||||
if (visit(ty, *ctv))
|
||||
|
@ -208,10 +213,8 @@ struct GenericTypeVarVisitor
|
|||
traverse(part);
|
||||
}
|
||||
}
|
||||
|
||||
else if (auto ptv = get<PrimitiveTypeVar>(ty))
|
||||
visit(ty, *ptv);
|
||||
|
||||
else if (auto ftv = get<FunctionTypeVar>(ty))
|
||||
{
|
||||
if (visit(ty, *ftv))
|
||||
|
@ -220,7 +223,6 @@ struct GenericTypeVarVisitor
|
|||
traverse(ftv->retTypes);
|
||||
}
|
||||
}
|
||||
|
||||
else if (auto ttv = get<TableTypeVar>(ty))
|
||||
{
|
||||
// Some visitors want to see bound tables, that's why we traverse the original type
|
||||
|
@ -243,7 +245,6 @@ struct GenericTypeVarVisitor
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (auto mtv = get<MetatableTypeVar>(ty))
|
||||
{
|
||||
if (visit(ty, *mtv))
|
||||
|
@ -252,7 +253,6 @@ struct GenericTypeVarVisitor
|
|||
traverse(mtv->metatable);
|
||||
}
|
||||
}
|
||||
|
||||
else if (auto ctv = get<ClassTypeVar>(ty))
|
||||
{
|
||||
if (visit(ty, *ctv))
|
||||
|
@ -267,10 +267,8 @@ struct GenericTypeVarVisitor
|
|||
traverse(*ctv->metatable);
|
||||
}
|
||||
}
|
||||
|
||||
else if (auto atv = get<AnyTypeVar>(ty))
|
||||
visit(ty, *atv);
|
||||
|
||||
else if (auto utv = get<UnionTypeVar>(ty))
|
||||
{
|
||||
if (visit(ty, *utv))
|
||||
|
@ -279,7 +277,6 @@ struct GenericTypeVarVisitor
|
|||
traverse(optTy);
|
||||
}
|
||||
}
|
||||
|
||||
else if (auto itv = get<IntersectionTypeVar>(ty))
|
||||
{
|
||||
if (visit(ty, *itv))
|
||||
|
@ -288,6 +285,24 @@ struct GenericTypeVarVisitor
|
|||
traverse(partTy);
|
||||
}
|
||||
}
|
||||
else if (!FFlag::LuauCompleteVisitor)
|
||||
return visit_detail::unsee(seen, ty);
|
||||
else if (get<LazyTypeVar>(ty))
|
||||
{
|
||||
// Visiting into LazyTypeVar may necessarily cause infinite expansion, so we don't do that on purpose.
|
||||
// Asserting also makes no sense, because the type _will_ happen here, most likely as a property of some ClassTypeVar
|
||||
// that doesn't need to be expanded.
|
||||
}
|
||||
else if (auto stv = get<SingletonTypeVar>(ty))
|
||||
visit(ty, *stv);
|
||||
else if (auto btv = get<BlockedTypeVar>(ty))
|
||||
visit(ty, *btv);
|
||||
else if (auto utv = get<UnknownTypeVar>(ty))
|
||||
visit(ty, *utv);
|
||||
else if (auto ntv = get<NeverTypeVar>(ty))
|
||||
visit(ty, *ntv);
|
||||
else
|
||||
LUAU_ASSERT(!"GenericTypeVarVisitor::traverse(TypeId) is not exhaustive!");
|
||||
|
||||
visit_detail::unsee(seen, ty);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "Luau/JsonEncoder.h"
|
||||
|
||||
#include "Luau/Ast.h"
|
||||
#include "Luau/ParseResult.h"
|
||||
#include "Luau/StringUtils.h"
|
||||
#include "Luau/Common.h"
|
||||
|
||||
|
@ -75,6 +76,11 @@ struct AstJsonEncoder : public AstVisitor
|
|||
writeRaw(std::string_view{&c, 1});
|
||||
}
|
||||
|
||||
void writeType(std::string_view propValue)
|
||||
{
|
||||
write("type", propValue);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void write(std::string_view propName, const T& value)
|
||||
{
|
||||
|
@ -98,7 +104,7 @@ struct AstJsonEncoder : public AstVisitor
|
|||
void write(double d)
|
||||
{
|
||||
char b[256];
|
||||
sprintf(b, "%g", d);
|
||||
sprintf(b, "%.17g", d);
|
||||
writeRaw(b);
|
||||
}
|
||||
|
||||
|
@ -111,8 +117,12 @@ struct AstJsonEncoder : public AstVisitor
|
|||
{
|
||||
if (c == '"')
|
||||
writeRaw("\\\"");
|
||||
else if (c == '\0')
|
||||
writeRaw("\\\0");
|
||||
else if (c == '\\')
|
||||
writeRaw("\\\\");
|
||||
else if (c < ' ')
|
||||
writeRaw(format("\\u%04x", c));
|
||||
else if (c == '\n')
|
||||
writeRaw("\\n");
|
||||
else
|
||||
writeRaw(c);
|
||||
}
|
||||
|
@ -189,10 +199,11 @@ struct AstJsonEncoder : public AstVisitor
|
|||
writeRaw("{");
|
||||
bool c = pushComma();
|
||||
if (local->annotation != nullptr)
|
||||
write("type", local->annotation);
|
||||
write("luauType", local->annotation);
|
||||
else
|
||||
write("type", nullptr);
|
||||
write("luauType", nullptr);
|
||||
write("name", local->name);
|
||||
writeType("AstLocal");
|
||||
write("location", local->location);
|
||||
popComma(c);
|
||||
writeRaw("}");
|
||||
|
@ -208,7 +219,7 @@ struct AstJsonEncoder : public AstVisitor
|
|||
{
|
||||
writeRaw("{");
|
||||
bool c = pushComma();
|
||||
write("type", name);
|
||||
writeType(name);
|
||||
writeNode(node);
|
||||
f();
|
||||
popComma(c);
|
||||
|
@ -358,6 +369,7 @@ struct AstJsonEncoder : public AstVisitor
|
|||
{
|
||||
writeRaw("{");
|
||||
bool c = pushComma();
|
||||
writeType("AstTypeList");
|
||||
write("types", typeList.types);
|
||||
if (typeList.tailType)
|
||||
write("tailType", typeList.tailType);
|
||||
|
@ -369,9 +381,10 @@ struct AstJsonEncoder : public AstVisitor
|
|||
{
|
||||
writeRaw("{");
|
||||
bool c = pushComma();
|
||||
writeType("AstGenericType");
|
||||
write("name", genericType.name);
|
||||
if (genericType.defaultValue)
|
||||
write("type", genericType.defaultValue);
|
||||
write("luauType", genericType.defaultValue);
|
||||
popComma(c);
|
||||
writeRaw("}");
|
||||
}
|
||||
|
@ -380,9 +393,10 @@ struct AstJsonEncoder : public AstVisitor
|
|||
{
|
||||
writeRaw("{");
|
||||
bool c = pushComma();
|
||||
writeType("AstGenericTypePack");
|
||||
write("name", genericTypePack.name);
|
||||
if (genericTypePack.defaultValue)
|
||||
write("type", genericTypePack.defaultValue);
|
||||
write("luauType", genericTypePack.defaultValue);
|
||||
popComma(c);
|
||||
writeRaw("}");
|
||||
}
|
||||
|
@ -404,6 +418,7 @@ struct AstJsonEncoder : public AstVisitor
|
|||
{
|
||||
writeRaw("{");
|
||||
bool c = pushComma();
|
||||
writeType("AstExprTableItem");
|
||||
write("kind", item.kind);
|
||||
switch (item.kind)
|
||||
{
|
||||
|
@ -419,6 +434,17 @@ struct AstJsonEncoder : public AstVisitor
|
|||
writeRaw("}");
|
||||
}
|
||||
|
||||
void write(class AstExprIfElse* node)
|
||||
{
|
||||
writeNode(node, "AstExprIfElse", [&]() {
|
||||
PROP(condition);
|
||||
PROP(hasThen);
|
||||
PROP(trueExpr);
|
||||
PROP(hasElse);
|
||||
PROP(falseExpr);
|
||||
});
|
||||
}
|
||||
|
||||
void write(class AstExprTable* node)
|
||||
{
|
||||
writeNode(node, "AstExprTable", [&]() {
|
||||
|
@ -431,11 +457,11 @@ struct AstJsonEncoder : public AstVisitor
|
|||
switch (op)
|
||||
{
|
||||
case AstExprUnary::Not:
|
||||
return writeString("not");
|
||||
return writeString("Not");
|
||||
case AstExprUnary::Minus:
|
||||
return writeString("minus");
|
||||
return writeString("Minus");
|
||||
case AstExprUnary::Len:
|
||||
return writeString("len");
|
||||
return writeString("Len");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,7 +567,7 @@ struct AstJsonEncoder : public AstVisitor
|
|||
|
||||
void write(class AstStatWhile* node)
|
||||
{
|
||||
writeNode(node, "AtStatWhile", [&]() {
|
||||
writeNode(node, "AstStatWhile", [&]() {
|
||||
PROP(condition);
|
||||
PROP(body);
|
||||
PROP(hasDo);
|
||||
|
@ -684,7 +710,8 @@ struct AstJsonEncoder : public AstVisitor
|
|||
writeRaw("{");
|
||||
bool c = pushComma();
|
||||
write("name", prop.name);
|
||||
write("type", prop.ty);
|
||||
writeType("AstDeclaredClassProp");
|
||||
write("luauType", prop.ty);
|
||||
popComma(c);
|
||||
writeRaw("}");
|
||||
}
|
||||
|
@ -731,8 +758,9 @@ struct AstJsonEncoder : public AstVisitor
|
|||
bool c = pushComma();
|
||||
|
||||
write("name", prop.name);
|
||||
writeType("AstTableProp");
|
||||
write("location", prop.location);
|
||||
write("type", prop.type);
|
||||
write("propType", prop.type);
|
||||
|
||||
popComma(c);
|
||||
writeRaw("}");
|
||||
|
@ -745,6 +773,24 @@ struct AstJsonEncoder : public AstVisitor
|
|||
PROP(indexer);
|
||||
});
|
||||
}
|
||||
|
||||
void write(struct AstTableIndexer* indexer)
|
||||
{
|
||||
if (indexer)
|
||||
{
|
||||
writeRaw("{");
|
||||
bool c = pushComma();
|
||||
write("location", indexer->location);
|
||||
write("indexType", indexer->indexType);
|
||||
write("resultType", indexer->resultType);
|
||||
popComma(c);
|
||||
writeRaw("}");
|
||||
}
|
||||
else
|
||||
{
|
||||
writeRaw("null");
|
||||
}
|
||||
}
|
||||
|
||||
void write(class AstTypeFunction* node)
|
||||
{
|
||||
|
@ -836,6 +882,12 @@ struct AstJsonEncoder : public AstVisitor
|
|||
return false;
|
||||
}
|
||||
|
||||
bool visit(class AstExprIfElse* node) override
|
||||
{
|
||||
write(node);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool visit(class AstExprLocal* node) override
|
||||
{
|
||||
write(node);
|
||||
|
@ -1093,6 +1145,42 @@ struct AstJsonEncoder : public AstVisitor
|
|||
write(node);
|
||||
return false;
|
||||
}
|
||||
|
||||
void writeComments(std::vector<Comment> commentLocations)
|
||||
{
|
||||
bool commentComma = false;
|
||||
for (Comment comment : commentLocations)
|
||||
{
|
||||
if (commentComma)
|
||||
{
|
||||
writeRaw(",");
|
||||
}
|
||||
else
|
||||
{
|
||||
commentComma = true;
|
||||
}
|
||||
writeRaw("{");
|
||||
bool c = pushComma();
|
||||
switch (comment.type)
|
||||
{
|
||||
case Lexeme::Comment:
|
||||
writeType("Comment");
|
||||
break;
|
||||
case Lexeme::BlockComment:
|
||||
writeType("BlockComment");
|
||||
break;
|
||||
case Lexeme::BrokenComment:
|
||||
writeType("BrokenComment");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
write("location", comment.location);
|
||||
popComma(c);
|
||||
writeRaw("}");
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::string toJson(AstNode* node)
|
||||
|
@ -1102,4 +1190,15 @@ std::string toJson(AstNode* node)
|
|||
return encoder.str();
|
||||
}
|
||||
|
||||
std::string toJson(AstNode* node, const std::vector<Comment>& commentLocations)
|
||||
{
|
||||
AstJsonEncoder encoder;
|
||||
encoder.writeRaw(R"({"root":)");
|
||||
node->visit(&encoder);
|
||||
encoder.writeRaw(R"(,"commentLocations":[)");
|
||||
encoder.writeComments(commentLocations);
|
||||
encoder.writeRaw("]}");
|
||||
return encoder.str();
|
||||
}
|
||||
|
||||
} // namespace Luau
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
LUAU_FASTFLAG(LuauLowerBoundsCalculation);
|
||||
LUAU_FASTFLAG(LuauNormalizeFlagIsConservative);
|
||||
LUAU_FASTFLAG(DebugLuauDeferredConstraintResolution);
|
||||
LUAU_FASTFLAGVARIABLE(LuauForceExportSurfacesToBeNormal, false);
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
|
@ -124,15 +125,21 @@ void Module::clonePublicInterface(InternalErrorReporter& ice)
|
|||
moduleScope2->returnType = returnType; // TODO varargPack
|
||||
}
|
||||
|
||||
ForceNormal forceNormal{&interfaceTypes};
|
||||
|
||||
if (FFlag::LuauLowerBoundsCalculation)
|
||||
{
|
||||
normalize(returnType, interfaceTypes, ice);
|
||||
if (FFlag::LuauForceExportSurfacesToBeNormal)
|
||||
forceNormal.traverse(returnType);
|
||||
if (varargPack)
|
||||
{
|
||||
normalize(*varargPack, interfaceTypes, ice);
|
||||
if (FFlag::LuauForceExportSurfacesToBeNormal)
|
||||
forceNormal.traverse(*varargPack);
|
||||
}
|
||||
}
|
||||
|
||||
ForceNormal forceNormal{&interfaceTypes};
|
||||
|
||||
if (exportedTypeBindings)
|
||||
{
|
||||
for (auto& [name, tf] : *exportedTypeBindings)
|
||||
|
@ -147,6 +154,16 @@ void Module::clonePublicInterface(InternalErrorReporter& ice)
|
|||
// We're about to freeze the memory. We know that the flag is conservative by design. Cyclic tables
|
||||
// won't be marked normal. If the types aren't normal by now, they never will be.
|
||||
forceNormal.traverse(tf.type);
|
||||
for (GenericTypeDefinition param : tf.typeParams)
|
||||
{
|
||||
forceNormal.traverse(param.ty);
|
||||
|
||||
if (param.defaultValue)
|
||||
{
|
||||
normalize(*param.defaultValue, interfaceTypes, ice);
|
||||
forceNormal.traverse(*param.defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +183,12 @@ void Module::clonePublicInterface(InternalErrorReporter& ice)
|
|||
{
|
||||
ty = clone(ty, interfaceTypes, cloneState);
|
||||
if (FFlag::LuauLowerBoundsCalculation)
|
||||
{
|
||||
normalize(ty, interfaceTypes, ice);
|
||||
|
||||
if (FFlag::LuauForceExportSurfacesToBeNormal)
|
||||
forceNormal.traverse(ty);
|
||||
}
|
||||
}
|
||||
|
||||
freeze(internalTypes);
|
||||
|
|
|
@ -31,6 +31,7 @@ LUAU_FASTINTVARIABLE(LuauCheckRecursionLimit, 300)
|
|||
LUAU_FASTINTVARIABLE(LuauVisitRecursionLimit, 500)
|
||||
LUAU_FASTFLAG(LuauKnowsTheDataModel3)
|
||||
LUAU_FASTFLAG(LuauAutocompleteDynamicLimits)
|
||||
LUAU_FASTFLAGVARIABLE(LuauExpectedTableUnionIndexerType, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauIndexSilenceErrors, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauLowerBoundsCalculation, false)
|
||||
LUAU_FASTFLAGVARIABLE(DebugLuauFreezeDuringUnification, false)
|
||||
|
@ -38,7 +39,6 @@ LUAU_FASTFLAGVARIABLE(LuauSelfCallAutocompleteFix2, false)
|
|||
LUAU_FASTFLAGVARIABLE(LuauReduceUnionRecursion, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauReturnAnyInsteadOfICE, false) // Eventually removed as false.
|
||||
LUAU_FASTFLAG(LuauNormalizeFlagIsConservative)
|
||||
LUAU_FASTFLAGVARIABLE(LuauReturnTypeInferenceInNonstrict, false)
|
||||
LUAU_FASTFLAGVARIABLE(DebugLuauSharedSelf, false);
|
||||
LUAU_FASTFLAGVARIABLE(LuauAlwaysQuantify, false);
|
||||
LUAU_FASTFLAGVARIABLE(LuauReportErrorsOnIndexerKeyMismatch, false)
|
||||
|
@ -50,6 +50,7 @@ LUAU_FASTFLAGVARIABLE(LuauCheckGenericHOFTypes, false)
|
|||
LUAU_FASTFLAGVARIABLE(LuauBinaryNeedsExpectedTypesToo, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauNeverTypesAndOperatorsInference, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauReturnsFromCallsitesAreNotWidened, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauCompleteVisitor, false)
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
|
@ -890,7 +891,7 @@ void TypeChecker::check(const ScopePtr& scope, const AstStatReturn& return_)
|
|||
|
||||
TypePackId retPack = checkExprList(scope, return_.location, return_.list, false, {}, expectedTypes).type;
|
||||
|
||||
if (FFlag::LuauReturnTypeInferenceInNonstrict ? FFlag::LuauLowerBoundsCalculation : useConstrainedIntersections())
|
||||
if (useConstrainedIntersections())
|
||||
{
|
||||
unifyLowerBound(retPack, scope->returnType, demoter.demotedLevel(scope->level), return_.location);
|
||||
return;
|
||||
|
@ -1292,6 +1293,11 @@ void TypeChecker::check(const ScopePtr& scope, const AstStatForIn& forin)
|
|||
for (size_t i = 2; i < varTypes.size(); ++i)
|
||||
unify(nilType, varTypes[i], forin.location);
|
||||
}
|
||||
else if (isNonstrictMode())
|
||||
{
|
||||
for (TypeId var : varTypes)
|
||||
unify(anyType, var, forin.location);
|
||||
}
|
||||
else
|
||||
{
|
||||
TypeId varTy = errorRecoveryType(loopScope);
|
||||
|
@ -1385,12 +1391,7 @@ void TypeChecker::check(const ScopePtr& scope, TypeId ty, const ScopePtr& funSco
|
|||
// 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 discrepancy will be caught in checkBlock.
|
||||
if (previouslyDefined)
|
||||
{
|
||||
if (FFlag::LuauReturnTypeInferenceInNonstrict && FFlag::LuauLowerBoundsCalculation)
|
||||
quantify(funScope, ty, exprName->location);
|
||||
|
||||
globalBindings[name] = oldBinding;
|
||||
}
|
||||
else
|
||||
globalBindings[name] = {quantify(funScope, ty, exprName->location), exprName->location};
|
||||
|
||||
|
@ -2365,9 +2366,16 @@ WithPredicate<TypeId> TypeChecker::checkExpr(const ScopePtr& scope, const AstExp
|
|||
{
|
||||
std::vector<TypeId> expectedResultTypes;
|
||||
for (TypeId expectedOption : expectedUnion)
|
||||
{
|
||||
if (const TableTypeVar* ttv = get<TableTypeVar>(follow(expectedOption)))
|
||||
{
|
||||
if (auto prop = ttv->props.find(key->value.data); prop != ttv->props.end())
|
||||
expectedResultTypes.push_back(prop->second.type);
|
||||
else if (FFlag::LuauExpectedTableUnionIndexerType && ttv->indexer && maybeString(ttv->indexer->indexType))
|
||||
expectedResultTypes.push_back(ttv->indexer->indexResultType);
|
||||
}
|
||||
}
|
||||
|
||||
if (expectedResultTypes.size() == 1)
|
||||
expectedResultType = expectedResultTypes[0];
|
||||
else if (expectedResultTypes.size() > 1)
|
||||
|
@ -3367,7 +3375,7 @@ std::pair<TypeId, ScopePtr> TypeChecker::checkFunctionSignature(const ScopePtr&
|
|||
TypePackId retPack;
|
||||
if (expr.returnAnnotation)
|
||||
retPack = resolveTypePack(funScope, *expr.returnAnnotation);
|
||||
else if (FFlag::LuauReturnTypeInferenceInNonstrict ? (!FFlag::LuauLowerBoundsCalculation && isNonstrictMode()) : isNonstrictMode())
|
||||
else if (isNonstrictMode())
|
||||
retPack = anyTypePack;
|
||||
else if (expectedFunctionType &&
|
||||
(!FFlag::LuauCheckGenericHOFTypes || (expectedFunctionType->generics.empty() && expectedFunctionType->genericPacks.empty())))
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "Luau/Transpiler.h"
|
||||
|
||||
#include "FileUtils.h"
|
||||
#include "Flags.h"
|
||||
|
||||
#ifdef CALLGRIND
|
||||
#include <valgrind/callgrind.h>
|
||||
|
@ -223,9 +224,7 @@ int main(int argc, char** argv)
|
|||
{
|
||||
Luau::assertHandler() = assertionHandler;
|
||||
|
||||
for (Luau::FValue<bool>* flag = Luau::FValue<bool>::list; flag; flag = flag->next)
|
||||
if (strncmp(flag->name, "Luau", 4) == 0)
|
||||
flag->value = true;
|
||||
setLuauFlagsDefault();
|
||||
|
||||
if (argc >= 2 && strcmp(argv[1], "--help") == 0)
|
||||
{
|
||||
|
@ -252,12 +251,14 @@ int main(int argc, char** argv)
|
|||
annotate = true;
|
||||
else if (strcmp(argv[i], "--timetrace") == 0)
|
||||
FFlag::DebugLuauTimeTracing.value = true;
|
||||
else if (strncmp(argv[i], "--fflags=", 9) == 0)
|
||||
setLuauFlags(argv[i] + 9);
|
||||
}
|
||||
|
||||
#if !defined(LUAU_ENABLE_TIME_TRACE)
|
||||
if (FFlag::DebugLuauTimeTracing)
|
||||
{
|
||||
printf("To run with --timetrace, Luau has to be built with LUAU_ENABLE_TIME_TRACE enabled\n");
|
||||
fprintf(stderr, "To run with --timetrace, Luau has to be built with LUAU_ENABLE_TIME_TRACE enabled\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -62,6 +62,7 @@ int main(int argc, char** argv)
|
|||
Luau::AstNameTable names(allocator);
|
||||
|
||||
Luau::ParseOptions options;
|
||||
options.captureComments = true;
|
||||
options.supportContinueStatement = true;
|
||||
options.allowTypeAnnotations = true;
|
||||
options.allowDeclarationSyntax = true;
|
||||
|
@ -78,7 +79,7 @@ int main(int argc, char** argv)
|
|||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
printf("%s", Luau::toJson(parseResult.root).c_str());
|
||||
printf("%s", Luau::toJson(parseResult.root, parseResult.commentLocations).c_str());
|
||||
|
||||
return parseResult.errors.size() > 0 ? 1 : 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
||||
#include "Luau/Common.h"
|
||||
#include "Luau/ExperimentalFlags.h"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static void setLuauFlag(std::string_view name, bool state)
|
||||
{
|
||||
for (Luau::FValue<bool>* flag = Luau::FValue<bool>::list; flag; flag = flag->next)
|
||||
{
|
||||
if (name == flag->name)
|
||||
{
|
||||
flag->value = state;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Warning: unrecognized flag '%.*s'.\n", int(name.length()), name.data());
|
||||
}
|
||||
|
||||
static void setLuauFlags(bool state)
|
||||
{
|
||||
for (Luau::FValue<bool>* flag = Luau::FValue<bool>::list; flag; flag = flag->next)
|
||||
if (strncmp(flag->name, "Luau", 4) == 0)
|
||||
flag->value = state;
|
||||
}
|
||||
|
||||
void setLuauFlagsDefault()
|
||||
{
|
||||
for (Luau::FValue<bool>* flag = Luau::FValue<bool>::list; flag; flag = flag->next)
|
||||
if (strncmp(flag->name, "Luau", 4) == 0 && !Luau::isFlagExperimental(flag->name))
|
||||
flag->value = true;
|
||||
}
|
||||
|
||||
void setLuauFlags(const char* list)
|
||||
{
|
||||
std::string_view rest = list;
|
||||
|
||||
while (!rest.empty())
|
||||
{
|
||||
size_t ending = rest.find(",");
|
||||
std::string_view element = rest.substr(0, ending);
|
||||
|
||||
if (size_t separator = element.find('='); separator != std::string_view::npos)
|
||||
{
|
||||
std::string_view key = element.substr(0, separator);
|
||||
std::string_view value = element.substr(separator + 1);
|
||||
|
||||
if (value == "true" || value == "True")
|
||||
setLuauFlag(key, true);
|
||||
else if (value == "false" || value == "False")
|
||||
setLuauFlag(key, false);
|
||||
else
|
||||
fprintf(stderr, "Warning: unrecognized value '%.*s' for flag '%.*s'.\n", int(value.length()), value.data(), int(key.length()),
|
||||
key.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (element == "true" || element == "True")
|
||||
setLuauFlags(true);
|
||||
else if (element == "false" || element == "False")
|
||||
setLuauFlags(false);
|
||||
else
|
||||
setLuauFlag(element, true);
|
||||
}
|
||||
|
||||
if (ending != std::string_view::npos)
|
||||
rest.remove_prefix(ending + 1);
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
||||
#pragma once
|
||||
|
||||
void setLuauFlagsDefault();
|
||||
void setLuauFlags(const char* list);
|
91
CLI/Repl.cpp
91
CLI/Repl.cpp
|
@ -8,9 +8,10 @@
|
|||
#include "Luau/BytecodeBuilder.h"
|
||||
#include "Luau/Parser.h"
|
||||
|
||||
#include "FileUtils.h"
|
||||
#include "Profiler.h"
|
||||
#include "Coverage.h"
|
||||
#include "FileUtils.h"
|
||||
#include "Flags.h"
|
||||
#include "Profiler.h"
|
||||
|
||||
#include "isocline.h"
|
||||
|
||||
|
@ -97,7 +98,11 @@ static int lua_require(lua_State* L)
|
|||
// return the module from the cache
|
||||
lua_getfield(L, -1, name.c_str());
|
||||
if (!lua_isnil(L, -1))
|
||||
{
|
||||
// L stack: _MODULES result
|
||||
return finishrequire(L);
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
std::optional<std::string> source = readFile(name + ".luau");
|
||||
|
@ -109,6 +114,7 @@ static int lua_require(lua_State* L)
|
|||
}
|
||||
|
||||
// module needs to run in a new thread, isolated from the rest
|
||||
// note: we create ML on main thread so that it doesn't inherit environment of L
|
||||
lua_State* GL = lua_mainthread(L);
|
||||
lua_State* ML = lua_newthread(GL);
|
||||
lua_xmove(GL, L, 1);
|
||||
|
@ -142,11 +148,12 @@ static int lua_require(lua_State* L)
|
|||
}
|
||||
}
|
||||
|
||||
// there's now a return value on top of ML; stack of L is MODULES thread
|
||||
// there's now a return value on top of ML; L stack: _MODULES ML
|
||||
lua_xmove(ML, L, 1);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -4, name.c_str());
|
||||
|
||||
// L stack: _MODULES ML result
|
||||
return finishrequire(L);
|
||||
}
|
||||
|
||||
|
@ -682,60 +689,11 @@ static int assertionHandler(const char* expr, const char* file, int line, const
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void setLuauFlags(bool state)
|
||||
{
|
||||
for (Luau::FValue<bool>* flag = Luau::FValue<bool>::list; flag; flag = flag->next)
|
||||
{
|
||||
if (strncmp(flag->name, "Luau", 4) == 0)
|
||||
flag->value = state;
|
||||
}
|
||||
}
|
||||
|
||||
static void setFlag(std::string_view name, bool state)
|
||||
{
|
||||
for (Luau::FValue<bool>* flag = Luau::FValue<bool>::list; flag; flag = flag->next)
|
||||
{
|
||||
if (name == flag->name)
|
||||
{
|
||||
flag->value = state;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Warning: --fflag unrecognized flag '%.*s'.\n\n", int(name.length()), name.data());
|
||||
}
|
||||
|
||||
static void applyFlagKeyValue(std::string_view element)
|
||||
{
|
||||
if (size_t separator = element.find('='); separator != std::string_view::npos)
|
||||
{
|
||||
std::string_view key = element.substr(0, separator);
|
||||
std::string_view value = element.substr(separator + 1);
|
||||
|
||||
if (value == "true")
|
||||
setFlag(key, true);
|
||||
else if (value == "false")
|
||||
setFlag(key, false);
|
||||
else
|
||||
fprintf(stderr, "Warning: --fflag unrecognized value '%.*s' for flag '%.*s'.\n\n", int(value.length()), value.data(), int(key.length()),
|
||||
key.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (element == "true")
|
||||
setLuauFlags(true);
|
||||
else if (element == "false")
|
||||
setLuauFlags(false);
|
||||
else
|
||||
setFlag(element, true);
|
||||
}
|
||||
}
|
||||
|
||||
int replMain(int argc, char** argv)
|
||||
{
|
||||
Luau::assertHandler() = assertionHandler;
|
||||
|
||||
setLuauFlags(true);
|
||||
setLuauFlagsDefault();
|
||||
|
||||
CliMode mode = CliMode::Unknown;
|
||||
CompileFormat compileFormat{};
|
||||
|
@ -818,27 +776,10 @@ int replMain(int argc, char** argv)
|
|||
else if (strcmp(argv[i], "--timetrace") == 0)
|
||||
{
|
||||
FFlag::DebugLuauTimeTracing.value = true;
|
||||
|
||||
#if !defined(LUAU_ENABLE_TIME_TRACE)
|
||||
printf("To run with --timetrace, Luau has to be built with LUAU_ENABLE_TIME_TRACE enabled\n");
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
else if (strncmp(argv[i], "--fflags=", 9) == 0)
|
||||
{
|
||||
std::string_view list = argv[i] + 9;
|
||||
|
||||
while (!list.empty())
|
||||
{
|
||||
size_t ending = list.find(",");
|
||||
|
||||
applyFlagKeyValue(list.substr(0, ending));
|
||||
|
||||
if (ending != std::string_view::npos)
|
||||
list.remove_prefix(ending + 1);
|
||||
else
|
||||
break;
|
||||
}
|
||||
setLuauFlags(argv[i] + 9);
|
||||
}
|
||||
else if (argv[i][0] == '-')
|
||||
{
|
||||
|
@ -848,6 +789,14 @@ int replMain(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
|
||||
#if !defined(LUAU_ENABLE_TIME_TRACE)
|
||||
if (FFlag::DebugLuauTimeTracing)
|
||||
{
|
||||
fprintf(stderr, "To run with --timetrace, Luau has to be built with LUAU_ENABLE_TIME_TRACE enabled\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
const std::vector<std::string> files = getSourceFiles(argc, argv);
|
||||
if (mode == CliMode::Unknown)
|
||||
{
|
||||
|
|
|
@ -61,12 +61,22 @@ public:
|
|||
void call(Label& label);
|
||||
void call(OperandX64 op);
|
||||
|
||||
void int3();
|
||||
|
||||
// AVX
|
||||
void vaddpd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||
void vaddps(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||
void vaddsd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||
void vaddss(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||
|
||||
void vsubsd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||
void vmulsd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||
void vdivsd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||
|
||||
void vxorpd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||
|
||||
void vcomisd(OperandX64 src1, OperandX64 src2);
|
||||
|
||||
void vsqrtpd(OperandX64 dst, OperandX64 src);
|
||||
void vsqrtps(OperandX64 dst, OperandX64 src);
|
||||
void vsqrtsd(OperandX64 dst, OperandX64 src1, OperandX64 src2);
|
||||
|
|
|
@ -37,8 +37,6 @@ enum class Condition
|
|||
Zero,
|
||||
NotZero,
|
||||
|
||||
// TODO: ordered and unordered floating-point conditions
|
||||
|
||||
Count
|
||||
};
|
||||
|
||||
|
|
|
@ -231,6 +231,7 @@ void AssemblyBuilderX64::lea(OperandX64 lhs, OperandX64 rhs)
|
|||
if (logText)
|
||||
log("lea", lhs, rhs);
|
||||
|
||||
LUAU_ASSERT(rhs.cat == CategoryX64::mem);
|
||||
placeBinaryRegAndRegMem(lhs, rhs, 0x8d, 0x8d);
|
||||
}
|
||||
|
||||
|
@ -314,6 +315,14 @@ void AssemblyBuilderX64::call(OperandX64 op)
|
|||
commit();
|
||||
}
|
||||
|
||||
void AssemblyBuilderX64::int3()
|
||||
{
|
||||
if (logText)
|
||||
log("int3");
|
||||
|
||||
place(0xcc);
|
||||
}
|
||||
|
||||
void AssemblyBuilderX64::vaddpd(OperandX64 dst, OperandX64 src1, OperandX64 src2)
|
||||
{
|
||||
placeAvx("vaddpd", dst, src1, src2, 0x58, false, AVX_0F, AVX_66);
|
||||
|
@ -334,6 +343,31 @@ void AssemblyBuilderX64::vaddss(OperandX64 dst, OperandX64 src1, OperandX64 src2
|
|||
placeAvx("vaddss", dst, src1, src2, 0x58, false, AVX_0F, AVX_F3);
|
||||
}
|
||||
|
||||
void AssemblyBuilderX64::vsubsd(OperandX64 dst, OperandX64 src1, OperandX64 src2)
|
||||
{
|
||||
placeAvx("vsubsd", dst, src1, src2, 0x5c, false, AVX_0F, AVX_F2);
|
||||
}
|
||||
|
||||
void AssemblyBuilderX64::vmulsd(OperandX64 dst, OperandX64 src1, OperandX64 src2)
|
||||
{
|
||||
placeAvx("vmulsd", dst, src1, src2, 0x59, false, AVX_0F, AVX_F2);
|
||||
}
|
||||
|
||||
void AssemblyBuilderX64::vdivsd(OperandX64 dst, OperandX64 src1, OperandX64 src2)
|
||||
{
|
||||
placeAvx("vdivsd", dst, src1, src2, 0x5e, false, AVX_0F, AVX_F2);
|
||||
}
|
||||
|
||||
void AssemblyBuilderX64::vxorpd(OperandX64 dst, OperandX64 src1, OperandX64 src2)
|
||||
{
|
||||
placeAvx("vxorpd", dst, src1, src2, 0x57, false, AVX_0F, AVX_66);
|
||||
}
|
||||
|
||||
void AssemblyBuilderX64::vcomisd(OperandX64 src1, OperandX64 src2)
|
||||
{
|
||||
placeAvx("vcomisd", src1, src2, 0x2f, false, AVX_0F, AVX_66);
|
||||
}
|
||||
|
||||
void AssemblyBuilderX64::vsqrtpd(OperandX64 dst, OperandX64 src)
|
||||
{
|
||||
placeAvx("vsqrtpd", dst, src, 0x51, false, AVX_0F, AVX_66);
|
||||
|
@ -494,9 +528,10 @@ void AssemblyBuilderX64::placeBinaryRegMemAndImm(OperandX64 lhs, OperandX64 rhs,
|
|||
LUAU_ASSERT(lhs.cat == CategoryX64::reg || lhs.cat == CategoryX64::mem);
|
||||
LUAU_ASSERT(rhs.cat == CategoryX64::imm);
|
||||
|
||||
SizeX64 size = lhs.base.size;
|
||||
SizeX64 size = lhs.cat == CategoryX64::reg ? lhs.base.size : lhs.memSize;
|
||||
LUAU_ASSERT(size == SizeX64::byte || size == SizeX64::dword || size == SizeX64::qword);
|
||||
|
||||
placeRex(lhs.base);
|
||||
placeRex(lhs);
|
||||
|
||||
if (size == SizeX64::byte)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
||||
#pragma once
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
|
||||
inline bool isFlagExperimental(const char* flag)
|
||||
{
|
||||
// Flags in this list are disabled by default in various command-line tools. They may have behavior that is not fully final,
|
||||
// or critical bugs that are found after the code has been submitted.
|
||||
static const char* kList[] =
|
||||
{
|
||||
"LuauLowerBoundsCalculation",
|
||||
nullptr, // makes sure we always have at least one entry
|
||||
};
|
||||
|
||||
for (const char* item: kList)
|
||||
if (item && strcmp(item, flag) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -27,6 +27,7 @@ LUAU_FASTFLAGVARIABLE(LuauCompileNoIpairs, false)
|
|||
|
||||
LUAU_FASTFLAGVARIABLE(LuauCompileFoldBuiltins, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauCompileBetterMultret, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauCompileFreeReassign, false)
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
|
@ -616,7 +617,7 @@ struct Compiler
|
|||
}
|
||||
else
|
||||
{
|
||||
AstExprLocal* le = arg->as<AstExprLocal>();
|
||||
AstExprLocal* le = FFlag::LuauCompileFreeReassign ? getExprLocal(arg) : arg->as<AstExprLocal>();
|
||||
Variable* lv = le ? variables.find(le->local) : nullptr;
|
||||
|
||||
// if the argument is a local that isn't mutated, we will simply reuse the existing register
|
||||
|
@ -2200,19 +2201,27 @@ struct Compiler
|
|||
compileLValueUse(lv, source, /* set= */ true);
|
||||
}
|
||||
|
||||
int getExprLocalReg(AstExpr* node)
|
||||
AstExprLocal* getExprLocal(AstExpr* node)
|
||||
{
|
||||
if (AstExprLocal* expr = node->as<AstExprLocal>())
|
||||
return expr;
|
||||
else if (AstExprGroup* expr = node->as<AstExprGroup>())
|
||||
return getExprLocal(expr->expr);
|
||||
else if (AstExprTypeAssertion* expr = node->as<AstExprTypeAssertion>())
|
||||
return getExprLocal(expr->expr);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int getExprLocalReg(AstExpr* node)
|
||||
{
|
||||
if (AstExprLocal* expr = getExprLocal(node))
|
||||
{
|
||||
// note: this can't check expr->upvalue because upvalues may be upgraded to locals during inlining
|
||||
Local* l = locals.find(expr->local);
|
||||
|
||||
return l && l->allocated ? l->reg : -1;
|
||||
}
|
||||
else if (AstExprGroup* expr = node->as<AstExprGroup>())
|
||||
return getExprLocalReg(expr->expr);
|
||||
else if (AstExprTypeAssertion* expr = node->as<AstExprTypeAssertion>())
|
||||
return getExprLocalReg(expr->expr);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
@ -2498,6 +2507,22 @@ struct Compiler
|
|||
if (options.optimizationLevel >= 1 && options.debugLevel <= 1 && areLocalsRedundant(stat))
|
||||
return;
|
||||
|
||||
// Optimization: for 1-1 local assignments, we can reuse the register *if* neither local is mutated
|
||||
if (FFlag::LuauCompileFreeReassign && options.optimizationLevel >= 1 && stat->vars.size == 1 && stat->values.size == 1)
|
||||
{
|
||||
if (AstExprLocal* re = getExprLocal(stat->values.data[0]))
|
||||
{
|
||||
Variable* lv = variables.find(stat->vars.data[0]);
|
||||
Variable* rv = variables.find(re->local);
|
||||
|
||||
if (int reg = getExprLocalReg(re); reg >= 0 && (!lv || !lv->written) && (!rv || !rv->written))
|
||||
{
|
||||
pushLocal(stat->vars.data[0], uint8_t(reg));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// note: allocReg in this case allocates into parent block register - note that we don't have RegScope here
|
||||
uint8_t vars = allocReg(stat, unsigned(stat->vars.size));
|
||||
|
||||
|
|
13
Makefile
13
Makefile
|
@ -31,15 +31,15 @@ ISOCLINE_SOURCES=extern/isocline/src/isocline.c
|
|||
ISOCLINE_OBJECTS=$(ISOCLINE_SOURCES:%=$(BUILD)/%.o)
|
||||
ISOCLINE_TARGET=$(BUILD)/libisocline.a
|
||||
|
||||
TESTS_SOURCES=$(wildcard tests/*.cpp) CLI/FileUtils.cpp CLI/Profiler.cpp CLI/Coverage.cpp CLI/Repl.cpp
|
||||
TESTS_SOURCES=$(wildcard tests/*.cpp) CLI/FileUtils.cpp CLI/Flags.cpp CLI/Profiler.cpp CLI/Coverage.cpp CLI/Repl.cpp
|
||||
TESTS_OBJECTS=$(TESTS_SOURCES:%=$(BUILD)/%.o)
|
||||
TESTS_TARGET=$(BUILD)/luau-tests
|
||||
|
||||
REPL_CLI_SOURCES=CLI/FileUtils.cpp CLI/Profiler.cpp CLI/Coverage.cpp CLI/Repl.cpp CLI/ReplEntry.cpp
|
||||
REPL_CLI_SOURCES=CLI/FileUtils.cpp CLI/Flags.cpp CLI/Profiler.cpp CLI/Coverage.cpp CLI/Repl.cpp CLI/ReplEntry.cpp
|
||||
REPL_CLI_OBJECTS=$(REPL_CLI_SOURCES:%=$(BUILD)/%.o)
|
||||
REPL_CLI_TARGET=$(BUILD)/luau
|
||||
|
||||
ANALYZE_CLI_SOURCES=CLI/FileUtils.cpp CLI/Analyze.cpp
|
||||
ANALYZE_CLI_SOURCES=CLI/FileUtils.cpp CLI/Flags.cpp CLI/Analyze.cpp
|
||||
ANALYZE_CLI_OBJECTS=$(ANALYZE_CLI_SOURCES:%=$(BUILD)/%.o)
|
||||
ANALYZE_CLI_TARGET=$(BUILD)/luau-analyze
|
||||
|
||||
|
@ -117,15 +117,18 @@ $(REPL_CLI_TARGET): LDFLAGS+=-lpthread
|
|||
fuzz-proto fuzz-prototest: LDFLAGS+=build/libprotobuf-mutator/src/libfuzzer/libprotobuf-mutator-libfuzzer.a build/libprotobuf-mutator/src/libprotobuf-mutator.a build/libprotobuf-mutator/external.protobuf/lib/libprotobuf.a
|
||||
|
||||
# pseudo targets
|
||||
.PHONY: all test clean coverage format luau-size
|
||||
.PHONY: all test clean coverage format luau-size aliases
|
||||
|
||||
all: $(REPL_CLI_TARGET) $(ANALYZE_CLI_TARGET) $(TESTS_TARGET)
|
||||
all: $(REPL_CLI_TARGET) $(ANALYZE_CLI_TARGET) $(TESTS_TARGET) aliases
|
||||
|
||||
aliases: luau luau-analyze
|
||||
|
||||
test: $(TESTS_TARGET)
|
||||
$(TESTS_TARGET) $(TESTS_ARGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD)
|
||||
rm -rf luau luau-analyze
|
||||
|
||||
coverage: $(TESTS_TARGET)
|
||||
$(TESTS_TARGET) --fflags=true
|
||||
|
|
|
@ -4,6 +4,7 @@ if(NOT ${CMAKE_VERSION} VERSION_LESS "3.19")
|
|||
target_sources(Luau.Common PRIVATE
|
||||
Common/include/Luau/Common.h
|
||||
Common/include/Luau/Bytecode.h
|
||||
Common/include/Luau/ExperimentalFlags.h
|
||||
)
|
||||
endif()
|
||||
|
||||
|
@ -220,6 +221,8 @@ if(TARGET Luau.Repl.CLI)
|
|||
CLI/Coverage.cpp
|
||||
CLI/FileUtils.h
|
||||
CLI/FileUtils.cpp
|
||||
CLI/Flags.h
|
||||
CLI/Flags.cpp
|
||||
CLI/Profiler.h
|
||||
CLI/Profiler.cpp
|
||||
CLI/Repl.cpp
|
||||
|
@ -231,6 +234,8 @@ if(TARGET Luau.Analyze.CLI)
|
|||
target_sources(Luau.Analyze.CLI PRIVATE
|
||||
CLI/FileUtils.h
|
||||
CLI/FileUtils.cpp
|
||||
CLI/Flags.h
|
||||
CLI/Flags.cpp
|
||||
CLI/Analyze.cpp)
|
||||
endif()
|
||||
|
||||
|
@ -321,6 +326,8 @@ if(TARGET Luau.CLI.Test)
|
|||
CLI/Coverage.cpp
|
||||
CLI/FileUtils.h
|
||||
CLI/FileUtils.cpp
|
||||
CLI/Flags.h
|
||||
CLI/Flags.cpp
|
||||
CLI/Profiler.h
|
||||
CLI/Profiler.cpp
|
||||
CLI/Repl.cpp
|
||||
|
|
|
@ -854,7 +854,7 @@ void lua_rawset(lua_State* L, int idx)
|
|||
StkId t = index2addr(L, idx);
|
||||
api_check(L, ttistable(t));
|
||||
if (hvalue(t)->readonly)
|
||||
luaG_runerror(L, "Attempt to modify a readonly table");
|
||||
luaG_readonlyerror(L);
|
||||
setobj2t(L, luaH_set(L, hvalue(t), L->top - 2), L->top - 1);
|
||||
luaC_barriert(L, hvalue(t), L->top - 1);
|
||||
L->top -= 2;
|
||||
|
@ -867,7 +867,7 @@ void lua_rawseti(lua_State* L, int idx, int n)
|
|||
StkId o = index2addr(L, idx);
|
||||
api_check(L, ttistable(o));
|
||||
if (hvalue(o)->readonly)
|
||||
luaG_runerror(L, "Attempt to modify a readonly table");
|
||||
luaG_readonlyerror(L);
|
||||
setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top - 1);
|
||||
luaC_barriert(L, hvalue(o), L->top - 1);
|
||||
L->top--;
|
||||
|
@ -890,7 +890,7 @@ int lua_setmetatable(lua_State* L, int objindex)
|
|||
case LUA_TTABLE:
|
||||
{
|
||||
if (hvalue(obj)->readonly)
|
||||
luaG_runerror(L, "Attempt to modify a readonly table");
|
||||
luaG_readonlyerror(L);
|
||||
hvalue(obj)->metatable = mt;
|
||||
if (mt)
|
||||
luaC_objbarrier(L, hvalue(obj), mt);
|
||||
|
|
|
@ -269,6 +269,11 @@ l_noret luaG_indexerror(lua_State* L, const TValue* p1, const TValue* p2)
|
|||
luaG_runerror(L, "attempt to index %s with %s", t1, t2);
|
||||
}
|
||||
|
||||
l_noret luaG_readonlyerror(lua_State* L)
|
||||
{
|
||||
luaG_runerror(L, "attempt to modify a readonly table");
|
||||
}
|
||||
|
||||
static void pusherror(lua_State* L, const char* msg)
|
||||
{
|
||||
CallInfo* ci = L->ci;
|
||||
|
|
|
@ -19,6 +19,7 @@ LUAI_FUNC l_noret luaG_concaterror(lua_State* L, StkId p1, StkId p2);
|
|||
LUAI_FUNC l_noret luaG_aritherror(lua_State* L, const TValue* p1, const TValue* p2, TMS op);
|
||||
LUAI_FUNC l_noret luaG_ordererror(lua_State* L, const TValue* p1, const TValue* p2, TMS op);
|
||||
LUAI_FUNC l_noret luaG_indexerror(lua_State* L, const TValue* p1, const TValue* p2);
|
||||
LUAI_FUNC l_noret luaG_readonlyerror(lua_State* L);
|
||||
|
||||
LUAI_FUNC LUA_PRINTF_ATTR(2, 3) l_noret luaG_runerrorL(lua_State* L, const char* fmt, ...);
|
||||
LUAI_FUNC void luaG_pusherror(lua_State* L, const char* error);
|
||||
|
|
|
@ -79,7 +79,7 @@ static void moveelements(lua_State* L, int srct, int dstt, int f, int e, int t)
|
|||
Table* dst = hvalue(L->base + (dstt - 1));
|
||||
|
||||
if (dst->readonly)
|
||||
luaG_runerror(L, "Attempt to modify a readonly table");
|
||||
luaG_readonlyerror(L);
|
||||
|
||||
int n = e - f + 1; /* number of elements to move */
|
||||
|
||||
|
@ -204,7 +204,7 @@ static int tmove(lua_State* L)
|
|||
Table* dst = hvalue(L->base + (tt - 1));
|
||||
|
||||
if (dst->readonly) /* also checked in moveelements, but this blocks resizes of r/o tables */
|
||||
luaG_runerror(L, "Attempt to modify a readonly table");
|
||||
luaG_readonlyerror( |