Javascript JS运行时中的Lua(Fengari):大整数的字符串表示形式后面有一个“尾随”;。0“;

Javascript JS运行时中的Lua(Fengari):大整数的字符串表示形式后面有一个“尾随”;。0“;,javascript,lua,Javascript,Lua,所以我有一个稍微复杂的问题。为了帮助解决整个问题,以下是背景: 我正在将一个应用程序转换为javascript,其中一部分应用程序使用lua来解释模板。我不控制这些模板。但是,模板解析器在lua中,它查看以%开头的行或包含标记的行的模板字符串。例如: this is output as is % for index, value in ipairs{1,2,3} do -- this is lua code that doesn't output index:<% index %>;

所以我有一个稍微复杂的问题。为了帮助解决整个问题,以下是背景:

我正在将一个应用程序转换为javascript,其中一部分应用程序使用lua来解释模板。我不控制这些模板。但是,模板解析器在lua中,它查看以
%
开头的行或包含
标记的行的模板字符串。例如:

this is output as is
% for index, value in ipairs{1,2,3} do -- this is lua code that doesn't output
index:<% index %>; value:<% value %>
% end
不以
%
开头的行被包装在lua助手
append(line\u contents)
函数中,如果它们有标签,比如
foobar
它会像
append('foo'…(tag\u variable)…'bar')一样被转换成
。以
%
开头的行被转换为lua代码(基本上是eval'd)。 这段代码运行良好,我可以控制解析模板的逻辑,并修改
append
helper。(但不是模板代码)

因此,当模板代码使用大约10位数字(整数)时,主要问题就会出现。在C-lua中,当在模板标记中使用值时,这些值的字符串表示形式只是整数部分。然而,在JS中Lua的应用程序中,其中一些数字的字符串表示有时会有一个尾随
.0
。这意味着不同运行时的输出不同。我在想办法解决这个问题

我认为这是因为Fengari依赖于JS
Number.prototype.toString
函数在需要时将数字格式化为字符串。看起来这是该函数的一个奇怪之处,一些点,一些10位以上的数字开始有尾随的十进制0。这是为lua定义的行为,而不是javascript,当内部表示使用浮点类型时,就会发生这种情况,正如Egor在注释中提到的那样。我在谷歌上搜索过,找不到任何关于这个问题的确切信息,但我相信这与数字的浮点表示有关。我可以使用
Number.prototype.toFixed
,但这并不能从全局解决问题。我还想更好地理解为什么会发生这种情况,并试图找到解决办法。我正在考虑以某种方式覆盖
Number.prototype.toString
,如果这能普遍适用的话,但我知道这会很棘手,如果可能的话。。。此外,我可以更改模板标记的包装方式,并在输出周围添加一个格式化帮助程序,这可能会在某些情况下解决此问题,但对于通过模板代码连接数字的情况没有帮助。。。那么我该怎么做呢


参考:以下是关于如何在JS中将数字表示为字符串的规范:。但我今天显然太累了,无法理解这个密集的数学定义:)。

在Fengari GitHub页面上回答:

fengari的行为故意与Lua 5.3相匹配。请参见
LUA\u COMPAT\u FLOATSTRING
和 和匹配的fengari代码:

fengari/src/lobject.js
(0c9631c中的第592至594行)

如果(!LUA_COMPAT_FLOATSTRING&&/^[-0123456789]+$/.test(str)){/*看起来像一个int?*/
str+='.0';/*将'.0'添加到结果中:lua_getlocaledecpoint作为优化删除*/
} 
这里记录了这一点:

fengari/src/luaconf.js
(0c9631c中的第123至129行)

/*
@@LUA_COMPAT_FLOATSTRING使LUA格式的整数浮点数不带
@@浮点数('.0')。
**默认情况下,即使在兼容模式下,此宏也不会打开,
**因为这并不是真正的不兼容。
*/ 
const LUA_COMPAT_FLOATSTRING=conf.LUA_COMPAT_FLOATSTRING | false;

这可以通过设置
process.env.FENGARICONF
JSON
字符串定义
LUA\u COMPAT\u FLOATSTRING

Fengari使用
int32
整数和
double
FP数字实现LUA 5.3来更改。10位数字不适合
int32
,因此它们是
双精度的。当Lua5.3将
double
转换为字符串时,它总是将小数点放在字符串中。要避免这种行为,请不要依赖标准Lua
tostring()
,也不要将数字与字符串连接起来。相反,用
string.format(“%.0f”,x)”转换数字。
您可以重新定义
tostring()
,但不能更改串联逻辑。
我正在考虑以某种方式覆盖Number.prototype.tostring
-这不会有帮助。顺便说一句,Fengari中的
int32
可能会在计算中被包围(例如:
65536*65536==0
),虽然您期待JS.IMO中常见的数字(
double
)行为,但获得与JS兼容性的正确方法是避免在Fengari中使用整数,例如:不要编写
x=123
,而是编写
x=123.0
,您可以通过在github上创建问题来询问。
this is output as is
index:1; value:1
index:2; value:2
index:3; value:3