A list of lsl-luau vs mono discrepancies observed on luau 2026-07-24 channel
tracked
TrishAce Resident
Here is a list of observed differences between Mono and LSL VM:
float nan = (float)"nan";
llOwnerSay((string)(nan >= 1.0)); // Output: LSO=math error Mono=1 LSL-LUAU=0
llOwnerSay((string)(nan <= 1.0)); // Output: LSO=math error Mono=1 LSL-LUAU=0
And a test script:
integer param(integer p)
{
return p++ + p;
}
default
{
state_entry()
{
integer a = 1;
llOwnerSay("1 (Mono = 0): " + (string)((a = 2) == a)); // Output in lsl-luau: 1
a = 1;
llOwnerSay("2 (Mono = 1): " + (string)(a++ == a)); // Output in lsl-luau: 0
llOwnerSay("3 (Mono = 2): " + (string)param(1)); // Output in lsl-luau: 3
// float->int cast
float f = 0.7;
llOwnerSay("4 (Mono = 7): " + (string)((integer)(f * 10.0))); // Output in lsl-luau: 6
integer i = 16777217;
float z = 0.0;
llOwnerSay("5 (Mono= 16777216): " + (string)((integer)(i + z))); // Output in lsl-luau: 16777217
// bit shifts
integer s = 32;
llOwnerSay("6 (Mono = 1): " + (string)(1 << s)); // Output in lsl-luau: 0
llOwnerSay("7 (Mono = -2147483648): " + (string)(1 << -1)); // Output in lsl-luau: 0
llOwnerSay("8 (Mono = 4): " + (string)(8 >> 33)); // Output in lsl-luau: 0
}
}
Log In
M
Mercury Linden
updated the status to
tracked
SuzannaLinn Resident
Another variation:
default
{
state_entry()
{
string str = "hello";
llOwnerSay("9 (Mono = 0): " + (string)((str = "bye") == str)); // Output in lsl-luau: 1
}
}
First script test, doing what the compiler is missing:
default
{
state_entry()
{
float nan = (float)"nan";
// Mono compiles >= as !( < ) and <= as !( > ) with a result of !nan
llOwnerSay((string)(!(nan < 1.0)));
llOwnerSay((string)(!(nan > 1.0)));
}
}
Second script test, doing what the compiler is missing:
integer param_fixed(integer p)
{
integer p_rhs = p; // save right side before left side with a parameter rewrites it
return p++ + p_rhs;
// compiler saves right side when needed with variables but not with parameters
}
default
{
state_entry()
{
integer a = 1;
integer a_rhs = a; // save right side before left side in a comparison rewrites it
llOwnerSay("1 (Mono = 0): " + (string)((a = 2) == a_rhs));
// compiler saves right side when needed with arithmetics, concatenation and list comparisons but not other comparisons
//
a = 1;
a_rhs = a; // save right side before left side in a comparison rewrites it
llOwnerSay("2 (Mono = 1): " + (string)(a++ == a_rhs));
// same as example 1
//
llOwnerSay("3 (Mono = 2): " + (string)param_fixed(1));
//
float f = 0.7;
float prod = f * 10.0; // force 6.999999999999999... to 7.0f
llOwnerSay("4 (Mono = 7): " + (string)((integer)prod));
// compiler uses 64 bit
//
integer i = 16777217;
float i_as_float = (float)i; // force integer to float to truncate to 16777216.0f
float z = 0.0;
llOwnerSay("5 (Mono = 16777216): " + (string)((integer)(i_as_float + z)));
// compiler uses 64 bit
//
// mask shift counts to 5 bits with & 31
integer s = 32;
llOwnerSay("6 (Mono = 1): " + (string)(1 << (s & 31)));
llOwnerSay("7 (Mono = -2147483648): " + (string)(1 << (-1 & 31)));
llOwnerSay("8 (Mono = 4): " + (string)(8 >> (33 & 31)));
// compiler doesn't mask, Luau returns 0 for shifts out of bounds
//
string str = "hello";
string str_rhs = str; // save right side before left side in a comparison rewrites it
llOwnerSay("9 (Mono = 0): " + (string)((str = "bye") == str_rhs));
// same as example 1
}
}