mirror of
https://github.com/luau-lang/luau.git
synced 2025-03-04 19:21:42 +00:00

# What's changed? Add program argument passing to scripts run using the Luau REPL! You can now pass `--program-args` (or shorthand `-a`) to the REPL which will treat all remaining arguments as arguments to pass to executed scripts. These values can be accessed through variadic argument expansion. You can read these values like so: ``` local args = {...} -- gets you an array of all the arguments ``` For example if we run the following script like `luau test.lua -a test1 test2 test3`: ``` -- test.lua print(...) ``` you should get the output: ``` test1 test2 test3 ``` ### Native Code Generation * Improve A64 lowering for vector operations by using vector instructions * Fix lowering issue in IR value location tracking! - A developer reported a divergence between code run in the VM and Native Code Generation which we have now fixed ### New Type Solver * Apply substitution to type families, and emit new constraints to reduce those further * More progress on reducing comparison (`lt/le`)type families * Resolve two major sources of cyclic types in the new solver ### Miscellaneous * Turned internal compiler errors (ICE's) into warnings and errors ------- Co-authored-by: Aaron Weiss <aaronweiss@roblox.com> Co-authored-by: Alexander McCord <amccord@roblox.com> Co-authored-by: Andy Friesen <afriesen@roblox.com> Co-authored-by: Aviral Goel <agoel@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com> --------- Co-authored-by: Aaron Weiss <aaronweiss@roblox.com> Co-authored-by: Alexander McCord <amccord@roblox.com> Co-authored-by: Andy Friesen <afriesen@roblox.com> Co-authored-by: Aviral Goel <agoel@roblox.com> Co-authored-by: David Cope <dcope@roblox.com> Co-authored-by: Lily Brown <lbrown@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com>
282 lines
11 KiB
C++
282 lines
11 KiB
C++
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
#include "Luau/IostreamHelpers.h"
|
|
#include "Luau/ToString.h"
|
|
#include "Luau/TypePath.h"
|
|
|
|
namespace Luau
|
|
{
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const Position& position)
|
|
{
|
|
return stream << "{ line = " << position.line << ", col = " << position.column << " }";
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const Location& location)
|
|
{
|
|
return stream << "Location { " << location.begin << ", " << location.end << " }";
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const AstName& name)
|
|
{
|
|
if (name.value)
|
|
return stream << name.value;
|
|
else
|
|
return stream << "<empty>";
|
|
}
|
|
|
|
template<typename T>
|
|
static void errorToString(std::ostream& stream, const T& err)
|
|
{
|
|
if constexpr (false)
|
|
{
|
|
}
|
|
else if constexpr (std::is_same_v<T, TypeMismatch>)
|
|
stream << "TypeMismatch { " << toString(err.wantedType) << ", " << toString(err.givenType) << " }";
|
|
else if constexpr (std::is_same_v<T, UnknownSymbol>)
|
|
stream << "UnknownSymbol { " << err.name << " , context " << err.context << " }";
|
|
else if constexpr (std::is_same_v<T, UnknownProperty>)
|
|
stream << "UnknownProperty { " << toString(err.table) << ", key = " << err.key << " }";
|
|
else if constexpr (std::is_same_v<T, NotATable>)
|
|
stream << "NotATable { " << toString(err.ty) << " }";
|
|
else if constexpr (std::is_same_v<T, CannotExtendTable>)
|
|
stream << "CannotExtendTable { " << toString(err.tableType) << ", context " << err.context << ", prop \"" << err.prop << "\" }";
|
|
else if constexpr (std::is_same_v<T, OnlyTablesCanHaveMethods>)
|
|
stream << "OnlyTablesCanHaveMethods { " << toString(err.tableType) << " }";
|
|
else if constexpr (std::is_same_v<T, DuplicateTypeDefinition>)
|
|
stream << "DuplicateTypeDefinition { " << err.name << " }";
|
|
else if constexpr (std::is_same_v<T, CountMismatch>)
|
|
stream << "CountMismatch { expected " << err.expected << ", got " << err.actual << ", context " << err.context << " }";
|
|
else if constexpr (std::is_same_v<T, FunctionDoesNotTakeSelf>)
|
|
stream << "FunctionDoesNotTakeSelf { }";
|
|
else if constexpr (std::is_same_v<T, FunctionRequiresSelf>)
|
|
stream << "FunctionRequiresSelf { }";
|
|
else if constexpr (std::is_same_v<T, OccursCheckFailed>)
|
|
stream << "OccursCheckFailed { }";
|
|
else if constexpr (std::is_same_v<T, UnknownRequire>)
|
|
stream << "UnknownRequire { " << err.modulePath << " }";
|
|
else if constexpr (std::is_same_v<T, IncorrectGenericParameterCount>)
|
|
{
|
|
stream << "IncorrectGenericParameterCount { name = " << err.name;
|
|
|
|
if (!err.typeFun.typeParams.empty() || !err.typeFun.typePackParams.empty())
|
|
{
|
|
stream << "<";
|
|
bool first = true;
|
|
for (auto param : err.typeFun.typeParams)
|
|
{
|
|
if (first)
|
|
first = false;
|
|
else
|
|
stream << ", ";
|
|
|
|
stream << toString(param.ty);
|
|
}
|
|
|
|
for (auto param : err.typeFun.typePackParams)
|
|
{
|
|
if (first)
|
|
first = false;
|
|
else
|
|
stream << ", ";
|
|
|
|
stream << toString(param.tp);
|
|
}
|
|
|
|
stream << ">";
|
|
}
|
|
|
|
stream << ", typeFun = " << toString(err.typeFun.type) << ", actualCount = " << err.actualParameters << " }";
|
|
}
|
|
else if constexpr (std::is_same_v<T, SyntaxError>)
|
|
stream << "SyntaxError { " << err.message << " }";
|
|
else if constexpr (std::is_same_v<T, CodeTooComplex>)
|
|
stream << "CodeTooComplex {}";
|
|
else if constexpr (std::is_same_v<T, UnificationTooComplex>)
|
|
stream << "UnificationTooComplex {}";
|
|
else if constexpr (std::is_same_v<T, UnknownPropButFoundLikeProp>)
|
|
{
|
|
stream << "UnknownPropButFoundLikeProp { key = '" << err.key << "', suggested = { ";
|
|
|
|
bool first = true;
|
|
for (Name name : err.candidates)
|
|
{
|
|
if (first)
|
|
first = false;
|
|
else
|
|
stream << ", ";
|
|
|
|
stream << "'" << name << "'";
|
|
}
|
|
|
|
stream << " }, table = " << toString(err.table) << " } ";
|
|
}
|
|
else if constexpr (std::is_same_v<T, GenericError>)
|
|
stream << "GenericError { " << err.message << " }";
|
|
else if constexpr (std::is_same_v<T, InternalError>)
|
|
stream << "InternalError { " << err.message << " }";
|
|
else if constexpr (std::is_same_v<T, CannotCallNonFunction>)
|
|
stream << "CannotCallNonFunction { " << toString(err.ty) << " }";
|
|
else if constexpr (std::is_same_v<T, ExtraInformation>)
|
|
stream << "ExtraInformation { " << err.message << " }";
|
|
else if constexpr (std::is_same_v<T, DeprecatedApiUsed>)
|
|
stream << "DeprecatedApiUsed { " << err.symbol << ", useInstead = " << err.useInstead << " }";
|
|
else if constexpr (std::is_same_v<T, ModuleHasCyclicDependency>)
|
|
{
|
|
stream << "ModuleHasCyclicDependency {";
|
|
|
|
bool first = true;
|
|
for (const ModuleName& name : err.cycle)
|
|
{
|
|
if (first)
|
|
first = false;
|
|
else
|
|
stream << ", ";
|
|
|
|
stream << name;
|
|
}
|
|
|
|
stream << "}";
|
|
}
|
|
else if constexpr (std::is_same_v<T, IllegalRequire>)
|
|
stream << "IllegalRequire { " << err.moduleName << ", reason = " << err.reason << " }";
|
|
else if constexpr (std::is_same_v<T, FunctionExitsWithoutReturning>)
|
|
stream << "FunctionExitsWithoutReturning {" << toString(err.expectedReturnType) << "}";
|
|
else if constexpr (std::is_same_v<T, DuplicateGenericParameter>)
|
|
stream << "DuplicateGenericParameter { " + err.parameterName + " }";
|
|
else if constexpr (std::is_same_v<T, CannotInferBinaryOperation>)
|
|
stream << "CannotInferBinaryOperation { op = " + toString(err.op) + ", suggested = '" +
|
|
(err.suggestedToAnnotate ? *err.suggestedToAnnotate : "") + "', kind "
|
|
<< err.kind << "}";
|
|
else if constexpr (std::is_same_v<T, MissingProperties>)
|
|
{
|
|
stream << "MissingProperties { superType = '" << toString(err.superType) << "', subType = '" << toString(err.subType) << "', properties = { ";
|
|
|
|
bool first = true;
|
|
for (Name name : err.properties)
|
|
{
|
|
if (first)
|
|
first = false;
|
|
else
|
|
stream << ", ";
|
|
|
|
stream << "'" << name << "'";
|
|
}
|
|
|
|
stream << " }, context " << err.context << " } ";
|
|
}
|
|
else if constexpr (std::is_same_v<T, SwappedGenericTypeParameter>)
|
|
stream << "SwappedGenericTypeParameter { name = '" + err.name + "', kind = " + std::to_string(err.kind) + " }";
|
|
else if constexpr (std::is_same_v<T, OptionalValueAccess>)
|
|
stream << "OptionalValueAccess { optional = '" + toString(err.optional) + "' }";
|
|
else if constexpr (std::is_same_v<T, MissingUnionProperty>)
|
|
{
|
|
stream << "MissingUnionProperty { type = '" + toString(err.type) + "', missing = { ";
|
|
|
|
bool first = true;
|
|
for (auto ty : err.missing)
|
|
{
|
|
if (first)
|
|
first = false;
|
|
else
|
|
stream << ", ";
|
|
|
|
stream << "'" << toString(ty) << "'";
|
|
}
|
|
|
|
stream << " }, key = '" + err.key + "' }";
|
|
}
|
|
else if constexpr (std::is_same_v<T, TypesAreUnrelated>)
|
|
stream << "TypesAreUnrelated { left = '" + toString(err.left) + "', right = '" + toString(err.right) + "' }";
|
|
else if constexpr (std::is_same_v<T, NormalizationTooComplex>)
|
|
stream << "NormalizationTooComplex { }";
|
|
else if constexpr (std::is_same_v<T, TypePackMismatch>)
|
|
stream << "TypePackMismatch { wanted = '" + toString(err.wantedTp) + "', given = '" + toString(err.givenTp) + "' }";
|
|
else if constexpr (std::is_same_v<T, DynamicPropertyLookupOnClassesUnsafe>)
|
|
stream << "DynamicPropertyLookupOnClassesUnsafe { " << toString(err.ty) << " }";
|
|
else if constexpr (std::is_same_v<T, UninhabitedTypeFamily>)
|
|
stream << "UninhabitedTypeFamily { " << toString(err.ty) << " }";
|
|
else if constexpr (std::is_same_v<T, UninhabitedTypePackFamily>)
|
|
stream << "UninhabitedTypePackFamily { " << toString(err.tp) << " }";
|
|
else if constexpr (std::is_same_v<T, WhereClauseNeeded>)
|
|
stream << "WhereClauseNeeded { " << toString(err.ty) << " }";
|
|
else if constexpr (std::is_same_v<T, PackWhereClauseNeeded>)
|
|
stream << "PackWhereClauseNeeded { " << toString(err.tp) << " }";
|
|
else if constexpr (std::is_same_v<T, CheckedFunctionCallError>)
|
|
stream << "CheckedFunctionCallError { expected = '" << toString(err.expected) << "', passed = '" << toString(err.passed)
|
|
<< "', checkedFunctionName = " << err.checkedFunctionName << ", argumentIndex = " << std::to_string(err.argumentIndex) << " }";
|
|
else if constexpr (std::is_same_v<T, NonStrictFunctionDefinitionError>)
|
|
stream << "NonStrictFunctionDefinitionError { functionName = '" + err.functionName + "', argument = '" + err.argument +
|
|
"', argumentType = '" + toString(err.argumentType) + "' }";
|
|
else if constexpr (std::is_same_v<T, PropertyAccessViolation>)
|
|
stream << "PropertyAccessViolation { table = " << toString(err.table) << ", prop = '" << err.key << "', context = " << err.context << " }";
|
|
else if constexpr (std::is_same_v<T, CheckedFunctionIncorrectArgs>)
|
|
stream << "CheckedFunction { functionName = '" + err.functionName + ", expected = " + std::to_string(err.expected) +
|
|
", actual = " + std::to_string(err.actual) + "}";
|
|
else if constexpr (std::is_same_v<T, UnexpectedTypeInSubtyping>)
|
|
stream << "UnexpectedTypeInSubtyping { ty = '" + toString(err.ty) + "' }";
|
|
else if constexpr (std::is_same_v<T, UnexpectedTypePackInSubtyping>)
|
|
stream << "UnexpectedTypePackInSubtyping { tp = '" + toString(err.tp) + "' }";
|
|
else
|
|
static_assert(always_false_v<T>, "Non-exhaustive type switch");
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const TypeErrorData& data)
|
|
{
|
|
auto cb = [&](const auto& e) {
|
|
return errorToString(stream, e);
|
|
};
|
|
visit(cb, data);
|
|
return stream;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const TypeError& error)
|
|
{
|
|
return stream << "TypeError { \"" << error.moduleName << "\", " << error.location << ", " << error.data << " }";
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const TableState& tv)
|
|
{
|
|
return stream << static_cast<std::underlying_type<TableState>::type>(tv);
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const Type& tv)
|
|
{
|
|
return stream << toString(tv);
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const TypePackVar& tv)
|
|
{
|
|
return stream << toString(tv);
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& stream, TypeId ty)
|
|
{
|
|
// we commonly use a null pointer when a type may not be present; we need to
|
|
// account for that here.
|
|
if (!ty)
|
|
return stream << "<nullptr>";
|
|
|
|
return stream << toString(ty);
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& stream, TypePackId tp)
|
|
{
|
|
// we commonly use a null pointer when a type may not be present; we need to
|
|
// account for that here.
|
|
if (!tp)
|
|
return stream << "<nullptr>";
|
|
|
|
return stream << toString(tp);
|
|
}
|
|
|
|
namespace TypePath
|
|
{
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const Path& path)
|
|
{
|
|
return stream << toString(path);
|
|
}
|
|
|
|
} // namespace TypePath
|
|
|
|
} // namespace Luau
|