Lua в JS runtime (Fengari): строковое представление больших целых чисел имеет в конце ".0" - PullRequest
0 голосов
/ 05 августа 2020

Итак, у меня немного сложная проблема. Чтобы помочь с общей проблемой, вот предыстория:

Я конвертирую приложение в 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

выведет:

this is output as is
index:1; value:1
index:2; value:2
index:3; value:3

строки, которые не начинаются с %, будут заключены в функцию lua helper append(line_contents), и если они есть теги, например foo<% tag_variable %>bar, он преобразуется как append('foo'..(tag_variable)..'bar'). Строки, начинающиеся с %, преобразуются в код lua (по сути, eval'd). Этот код работает хорошо, и я могу управлять logi c, который анализирует шаблон, и изменять помощник append. (Но не код шаблона)

Итак, основная проблема возникает, когда код шаблона работает с ~ 10-di git числами (целыми числами). В C - lua их строковое представление - это просто целая часть, когда значение используется в теге шаблона. Однако в среде выполнения Fengari из Lua в JS строковое представление некоторых из этих чисел иногда заканчивается .0. Это означает, что вывод варьируется в зависимости от времени выполнения. Я пытаюсь найти способы исправить это.

Я считаю, что это вызвано тем, что Fengari полагается на функцию JS Number.prototype.toString для форматирования чисел в виде строк, когда это необходимо. И похоже, что это странность этой функции, , что в какой-то момент некоторые числа 10+ di git начинают иметь завершающие десятичные нули. Это определенное поведение для lua, а не javascript, и происходит, когда внутреннее представление использует тип с плавающей запятой, как Егор упоминает в комментариях . Я погуглил и не нашел точного упоминания об этой проблеме, но считаю, что это связано с представлением чисел с плавающей запятой. Я мог бы использовать Number.prototype.toFixed, но это не решает проблему глобально. Я также хочу лучше понять, почему это происходит, а также попытаться найти решение. Я рассматриваю возможность перезаписи Number.prototype.toString, если это будет работать повсеместно, но я знаю, что это будет сложно, если это вообще возможно ... Кроме того, я мог бы изменить способ обертывания тегов шаблона и добавить помощник по форматированию вокруг вывода, и это может решить проблему в некоторых случаях, но это не помогает в тех случаях, когда числа объединяются с помощью кода шаблона ... Итак, как я могу подойти к этому?

Ссылка: вот SPE c на как числа представлены в виде строк в JS: https://www.ecma-international.org/ecma-262/7.0/#sec -tostring-application-to-the-number-type . Но я, видимо, слишком устал, чтобы понимать это плотное математическое определение сегодня :).

1 Ответ

1 голос
/ 07 августа 2020

Ответ на странице Fengari GitHub здесь: https://github.com/fengari-lua/fengari/issues/183

поведение fengari намеренно совпадает с Lua 5.3 здесь. См. LUA_COMPAT_FLOATSTRING и https://www.lua.org/source/5.3/lobject.c.html#luaO_tostring и соответствующий код фенгари:

fengari/src/lobject.js (строки с 592 по 594 в 0c9631 c)

 if (!LUA_COMPAT_FLOATSTRING && /^[-0123456789]+$/.test(str)) {  /* looks like an int? */ 
     str += '.0'; /* adds '.0' to result: lua_getlocaledecpoint removed as optimisation */ 
 } 

Это задокументировано здесь:

fengari/src/luaconf.js (Строки с 123 по 129 в 0c9631 c)

 /* 
 @@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a 
 @@ a float mark ('.0'). 
 ** This macro is not on by default even in compatibility mode, 
 ** because this is not really an incompatibility. 
 */ 
 const LUA_COMPAT_FLOATSTRING = conf.LUA_COMPAT_FLOATSTRING || false; 

Это можно изменить, установив process.env.FENGARICONF со строкой JSON, определяющей LUA_COMPAT_FLOATSTRING

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...