mirror of
https://github.com/luau-lang/luau.git
synced 2025-05-04 10:33:46 +01:00
Fix tests, but introduce a new snaggle
This commit is contained in:
parent
cfe339f994
commit
e1a229aa80
3 changed files with 67 additions and 11 deletions
|
@ -1522,17 +1522,15 @@ struct Compiler
|
||||||
if (formatStringIndex < 0)
|
if (formatStringIndex < 0)
|
||||||
CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile");
|
CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile");
|
||||||
|
|
||||||
// INTERP CODE REVIEW: Why do I need this?
|
RegScope rs(this);
|
||||||
// If I don't, it emits `LOADK R1 K1` instead of `LOADK R2 K1`,
|
// unsigned int top = regTop;
|
||||||
// and it gives the error "missing argument 2".
|
|
||||||
allocReg(expr, 1);
|
|
||||||
|
|
||||||
emitLoadK(target, formatStringIndex);
|
uint8_t baseReg = allocReg(expr, 2 + expr->expressions.size);
|
||||||
|
|
||||||
uint8_t baseExprReg = allocReg(expr, expr->expressions.size);
|
emitLoadK(baseReg, formatStringIndex);
|
||||||
|
|
||||||
for (size_t index = 0; index < expr->expressions.size; ++index)
|
for (size_t index = 0; index < expr->expressions.size; ++index)
|
||||||
compileExpr(expr->expressions.data[index], baseExprReg + index, targetTemp);
|
compileExprTempTop(expr->expressions.data[index], uint8_t(baseReg + 2 + index));
|
||||||
|
|
||||||
BytecodeBuilder::StringRef formatMethod = sref(AstName("format"));
|
BytecodeBuilder::StringRef formatMethod = sref(AstName("format"));
|
||||||
|
|
||||||
|
@ -1540,9 +1538,10 @@ struct Compiler
|
||||||
if (formatMethodIndex < 0)
|
if (formatMethodIndex < 0)
|
||||||
CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile");
|
CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile");
|
||||||
|
|
||||||
bytecode.emitABC(LOP_NAMECALL, target, target, uint8_t(BytecodeBuilder::getStringHash(formatMethod)));
|
bytecode.emitABC(LOP_NAMECALL, baseReg, baseReg, uint8_t(BytecodeBuilder::getStringHash(formatMethod)));
|
||||||
bytecode.emitAux(formatMethodIndex);
|
bytecode.emitAux(formatMethodIndex);
|
||||||
bytecode.emitABC(LOP_CALL, target, uint8_t(expr->expressions.size + 2), 2);
|
bytecode.emitABC(LOP_CALL, baseReg, uint8_t(expr->expressions.size + 2), 2);
|
||||||
|
bytecode.emitABC(LOP_MOVE, target, baseReg, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t encodeHashSize(unsigned int hashSize)
|
static uint8_t encodeHashSize(unsigned int hashSize)
|
||||||
|
|
|
@ -1241,6 +1241,62 @@ TEST_CASE("InterpStringWithNoExpressions")
|
||||||
CHECK_EQ(compileFunction0(R"(return "hello")"), compileFunction0("return `hello`"));
|
CHECK_EQ(compileFunction0(R"(return "hello")"), compileFunction0("return `hello`"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* INTERP CODE REVIEW: This test fails, but its not clear to me why.
|
||||||
|
*
|
||||||
|
* One reason is that LOP_MOVE is added indiscriminately with interpolated strings, whereas
|
||||||
|
* standard namecalls only add it where necessary.
|
||||||
|
* I am not sure how to fix that, but at least understand why it happens.
|
||||||
|
*
|
||||||
|
* The second reason, however, is that the registers are completely different for both.
|
||||||
|
* Since the conformance tests pass, this might just be a difference without a distinction,
|
||||||
|
* like if "format" is being registered before the other strings, for instance.
|
||||||
|
*
|
||||||
|
* (""):format() codegen:
|
||||||
|
* LOADK R0 K0
|
||||||
|
* LOADK R2 K1
|
||||||
|
* NAMECALL R0 R0 K2
|
||||||
|
* CALL R0 2 1
|
||||||
|
* RETURN R0 0
|
||||||
|
*
|
||||||
|
* Interpolated string codegen:
|
||||||
|
* LOADK R1 K0
|
||||||
|
* LOADK R3 K1
|
||||||
|
* NAMECALL R1 R1 K2
|
||||||
|
* CALL R1 2 1
|
||||||
|
* MOVE R0 R1
|
||||||
|
* RETURN R0 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TEST_CASE("InterpStringZeroCost")
|
||||||
|
// {
|
||||||
|
// ScopedFastFlag sff{"LuauInterpolatedStringBaseSupport", true};
|
||||||
|
|
||||||
|
// CHECK_EQ(
|
||||||
|
// "\n" + compileFunction0(R"(local _ = ("hello, %*!"):format("world"))"),
|
||||||
|
// "\n" + compileFunction0(R"(local _ = `hello, {"world"}!`)")
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
TEST_CASE("InterpStringRegisterCleanup")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sff{"LuauInterpolatedStringBaseSupport", true};
|
||||||
|
|
||||||
|
CHECK_EQ(
|
||||||
|
"\n" + compileFunction0(R"(
|
||||||
|
local a, b, c = nil, "um", "uh oh"
|
||||||
|
a = ("foo%*"):format("bar")
|
||||||
|
print(a)
|
||||||
|
)"),
|
||||||
|
|
||||||
|
"\n" + compileFunction0(R"(
|
||||||
|
local a, b, c = nil, "um", "uh oh"
|
||||||
|
a = `foo{"bar"}`
|
||||||
|
print(a)
|
||||||
|
)")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("ConstantFoldArith")
|
TEST_CASE("ConstantFoldArith")
|
||||||
{
|
{
|
||||||
CHECK_EQ("\n" + compileFunction0("return 10 + 2"), R"(
|
CHECK_EQ("\n" + compileFunction0("return 10 + 2"), R"(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
local function assertEq(left, right)
|
local function assertEq(left, right)
|
||||||
assert(typeof(left) == "string")
|
assert(typeof(left) == "string", "left is a " .. typeof(left))
|
||||||
assert(typeof(right) == "string")
|
assert(typeof(right) == "string", "right is a " .. typeof(right))
|
||||||
|
|
||||||
if left ~= right then
|
if left ~= right then
|
||||||
error(string.format("%q ~= %q", left, right))
|
error(string.format("%q ~= %q", left, right))
|
||||||
|
@ -8,6 +8,7 @@ local function assertEq(left, right)
|
||||||
end
|
end
|
||||||
|
|
||||||
assertEq(`hello {"world"}`, "hello world")
|
assertEq(`hello {"world"}`, "hello world")
|
||||||
|
assertEq(`Welcome {"to"} {"Luau"}!`, "Welcome to Luau!")
|
||||||
|
|
||||||
assertEq(`2 + 2 = {2 + 2}`, "2 + 2 = 4")
|
assertEq(`2 + 2 = {2 + 2}`, "2 + 2 = 4")
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue