Fix tests, but introduce a new snaggle

This commit is contained in:
Kampfkarren 2022-07-27 23:29:57 -07:00
parent cfe339f994
commit e1a229aa80
3 changed files with 67 additions and 11 deletions

View file

@ -1522,17 +1522,15 @@ struct Compiler
if (formatStringIndex < 0)
CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile");
// INTERP CODE REVIEW: Why do I need this?
// If I don't, it emits `LOADK R1 K1` instead of `LOADK R2 K1`,
// and it gives the error "missing argument 2".
allocReg(expr, 1);
RegScope rs(this);
// unsigned int top = regTop;
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)
compileExpr(expr->expressions.data[index], baseExprReg + index, targetTemp);
compileExprTempTop(expr->expressions.data[index], uint8_t(baseReg + 2 + index));
BytecodeBuilder::StringRef formatMethod = sref(AstName("format"));
@ -1540,9 +1538,10 @@ struct Compiler
if (formatMethodIndex < 0)
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.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)

View file

@ -1241,6 +1241,62 @@ TEST_CASE("InterpStringWithNoExpressions")
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")
{
CHECK_EQ("\n" + compileFunction0("return 10 + 2"), R"(

View file

@ -1,6 +1,6 @@
local function assertEq(left, right)
assert(typeof(left) == "string")
assert(typeof(right) == "string")
assert(typeof(left) == "string", "left is a " .. typeof(left))
assert(typeof(right) == "string", "right is a " .. typeof(right))
if left ~= right then
error(string.format("%q ~= %q", left, right))
@ -8,6 +8,7 @@ local function assertEq(left, right)
end
assertEq(`hello {"world"}`, "hello world")
assertEq(`Welcome {"to"} {"Luau"}!`, "Welcome to Luau!")
assertEq(`2 + 2 = {2 + 2}`, "2 + 2 = 4")