-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Impacts of migrating to Lua 5.3 #2808
Comments
As a codicil, the above "Detailed Stuff" is extracted from the official Lua project documentation. There are more impacts because Lua53 subsumes many of the eLua patches and so we need to make other changes to mask these. For example eLua has two function types: one for Lua and standard C functions and a new one for lightweight C functions. Lua53 just treats them all as functions though you can probe the subtype if you really need to, so I need to change common expressions like |
+2 :D Thanks heaps for all your looking into and summarising of this, Terry! There's no doubt that this is a significant upgrade, but I do think it's something we should do. My recommendation would be to leave a I do have one question on the above - you say that "modules are not expected to set global variables anymore". But how do we register our modules into the global scope then? I mean, |
@jmattsson, I've done a series of related issues labelled Lua 5.3, covering various aspects of this.
|
Certainly 👍 if the Lua experts are aligned :) Do you envision a gradual migration of our modules to the Lua53 concepts or one single big change? |
@devsaurus, we will need to have all the modules patched before I release the first Lua53 PR, but the encapsulation will make them backwards compatible. I think it sensible to do this in 2 or 3 batches:
When this is all complete, all directories other than the One other goal that I would like to consider and implement if possible is making the module source ESP32 / ESP 8266 agnostic, except of course where the are architectural reasons why the module won't v work on one variant. |
Thank you Terry for all the details and for devising a plan!
👍 My only request is that none of this lands on |
Big 👍 About
Also - I think that it would be a good idea to only make setting for precision for floating numbers (double or single) in builds and support that instead of changing both floating numbers and integers to 64 bit. If someone wants to use 64bit integers another setting in |
Don't worry Marcel, this one is sort of a biggy so I agree entirely that it needs to be coordinated carefully will |
Hi @galjonsfigur, I think that you've earned enough karma to have a say here. 😄 I am going to take a more relaxed view on compatibility issues when it comes to our Lua IoT developers, simply because we are potentially going to bugger up a lot more production code out there if we don't compared to the libraries where (in the end) I can do the bulk edit myself with less effort than trying to engage the original contributors to get up to speed and do the heavy lifting. Lua 5.3 has various compatibility settings which enable thing like the top level Thanks for the heads-up on patterns, but this is one where I really don't want to hybridise 5.3, so we should just accept the hit and appologise to our users. As you correctly mention the issue of precision is going to prove a PITA, IMO. I think that we are going to have to support both 32-bit and 64-bit build variants. That is with 32 bit integers and floats or 64 bit integers and floats. The ESP32 xtensa cell has 32 bit floating point in the hardware, but the ESP8266 has a lot of the standard double library routines in the bootROM code, so ironically 64-bit FP will probably run faster on the ESP8266 than 32-bit. The simplest from my PoV would be 32-bit integers and 64-bit FP, but this is really the worst of both worlds. Anyway please track all of my issues, PRs and work on this and I would really value your feedback. |
Thanks for opinion! I just checked performance impact when using double over single precision floating numbers and the results: (Just simple modification to Arduino sketch so this is not really a great example)
Those are more indicators than benchmark but I think there will be a performance penalty when using 64bit floating point numbers, at least on ESP8266. My point it that I don't think end user would have to worry about what to set as it's now with float or integer build. And AFAIK Lua 5.3 allows to make a combinations of 32bit int and float, 64bit int and float, 32bit int and double or 64bit int and double. Those settings can be exposed somewhere in I just don't see a reason to bother with 64 vs 32 bit integer values. I think I would be a good idea to go for 32 bit by default and just leave option for floating point numbers when some application would need better precision in Lua script, because as for C side of things, sensor readings are processed using double precision floating point numbers (for example I will try to write something constructive on other isuses related to Lua 5.3, but I'm tracking them and it's a wonderful work! |
In my experience -- for what its worth -- apps spend so little time in true floating point computation that the runtime double vs single is pretty irrelevant. (We spend for more time in the Lua GC for example.) The main issues relate to getting the built to compile and execute cleanly. RAM use is an issue and the fundamental storage element, the |
I now have a baseline for lessons learnt from the integration of eLua features into core LuaI don't think unfair to describe the the An example of this is in the approach to add support for readonly tables and light function references.
if (lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TLIGHTFUNCTION) {
if ( lua_isfunction(L,2)) { On reflecting how the core team implemented these changes, I feel that their approach is more sound and better aligned to the rest of the Lua architecture: the code is simpler and runs faster. So for example I have to ask myself "why do we have or need light functions and expose them at the C API level?" And the answer is that there is no good reason, IMO. Getting rid of them in our Lua code base will simplify code modules in a lua version independent way. See #2866 for further discussion. |
I think that I've addressed all of the open issues here through the recent PRs, so I am closing this. |
I have done a roll up of the changes in moving from Lua 5.1 (referred to as Lua51) to Lua 5.3 (Lua53). (This combines any changes introduced in Lua 5.2 and also removes the points that aren't relevant to NodeMCU implementation (e.g.
os
andio
stuff and unimplementedmath
anddebug
components.) Broadly these changes fall into three broad categories:Changes in the Lua language itself. The biggy here is the introduction of an integer subtype for numbers which makes the need to separate integer and float builds redundant.
Changes in the Lua libraries. These might break existing examples and user applications, but for the majority of users these won't impact their applications. In general they are pretty easy to code around. For example
loadstring()
functionality has been moved intoload()
so replacingloadstring
by(loadstring or load)
means the Lua code works under 5.1 and 5.3.Changes in the C API. These might break existing C library modules. An example here is that all of the different signed and unsigned integer variants of the API calls have been dropped in favour of the core set which return
lua_Integer
. Type casting and conversion is left to the application program. So no moreluaL_checkint()
orluaL_checklong()
onlyluaL_checkinteger()
which returns alua_Integer
.Clearly I will deal with all of the core stuff (the
app/lua
toapp/lua53
directories and core NodeMCU modules such asnode
,file
, etc.) as part of the PR.Having done a scan of the
lua_examples
andlua_modules
directories there are very few cases where moving to Lua5.3 will break the application, and I can put through a bulk edit so that the source is Lua53 compatible (such as the aboveloadstring
use). However, I can't commit to testing all of these changes, but they should just work out of the box.I can also do a similar bulk edit so that the
app/modules
directly compiles cleanly on both build variants, but again I just don't have the bandwidth to test every module.So as I see it, given the reality that the other committers will spend little if any effort in supporting this upgrade, we have two alternatives:
luac.cross
andnode.compile()
because of these integer edge effects. We might get similar issues moving from 5.1 to 5.3.)Before I go any further, I would like to reach a quorum consensus from the committers . I personally can't think of any in-between options and that (2) is preferable to (1).
The detailed stuff
Major Changes in the Language
The main difference with Lua53 is the introduction of an integer subtype for numbers. Although this change should not affect "normal" computations, some computations (mainly those that involve some kind of overflow) can give different results. You can fix these differences by forcing a number to be a float (in Lua51 all numbers were float), in particular writing constants with an ending
.0
or usingx = x + 0.0
to convert a variable. (This recommendation is only for a quick fix for an occasional incompatibility, as it is not a general guideline for good programming; for this, use floats where you need floats and integers where you need integers.)The conversion of a float to a string now adds a
.0
suffix to the result if it looks like an integer. (For instance, the float 2.0 will be printed as2.0
, not as2
.) You should always use an explicit format when you need a specific format for numbers.(Formally this is not an incompatibility, because Lua does not specify how numbers are formatted as strings, but some programs assumed a specific format.)Minor Changes in the Language
These will directly impact few if any NodeMCU applications:
The concept of environment changed. Only Lua functions have environments. To set the environment of a Lua function, use the variable
_ENV
or the functionload
. C functions no longer have environments. Use an upvalue with a shared table if you need to keep shared state among several C functions. (You may useluaL_setfuncs
to open a C library with all functions sharing a common upvalue.) To manipulate the "environment" of a userdata (which is now called user value), use the new functionslua_getuservalue
andlua_setuservalue
.Lua identifiers cannot use locale-dependent letters.
Doing a step or a full collection in the garbage collector does not restart the collector if it has been stopped.
Weak tables with weak keys now perform like ephemeron tables.
Equality between function values has changed. Now, a function definition may not create a new value;
it may reuse some previous value if there is no observable difference to the new function.
Changes in the Lua libraries (which might impact lua_examples, lua_modules and user applications)
Function
module
is deprecated. It is easy to set up a module with regular Lua code. Modules are not expected to set global variables.Functions
setfenv
andgetfenv
were removed, because of the changes in environments.Function
loadstring
is deprecated. Useload
instead; it now accepts string argumentsand are exactly equivalent to
loadstring
.Function
table.maxn
is deprecated. Write it in Lua if you really need it.Function
unpack
was moved into the table library and therefore must be called astable.unpack
.Character class
%z
in patterns is deprecated, as now patterns may contain '\0
' as a regular character.The table
package.loaders
was renamedpackage.searchers
.Lua does not have bytecode verification anymore. So, all functions that load code (
load
andloadfile
) are potentially insecure when loading untrusted binary data. (Actually, those functions were already insecure because of flaws in the verification algorithm.) When in doubt, use themode
argument of those functions to restrict them to loading textual chunks.The
bit32
library has been deprecated. It is easy to require a compatible external library or, better yet, to replace its functions with appropriate bitwise operations. (Keep in mind thatbit32
operates on 32-bit integers, while the bitwise operators in Lua5.3 operate on Lua integers, which can have 32 or 64 bits, depending on the build configuration)The Table library now respects metamethods for setting and getting elements.
The
ipairs
iterator now respects metamethods and its__ipairs
metamethod has been deprecated.The
pow
functions is deprecated in the mathematical library. You can replacemath.pow(x,y)
withx^y
.The call
collectgarbage("count")
now returns only one result. (You can compute that second result from the fractional part of the first result.)Changes in the API which impact NodeMCU C modules
Pseudoindex
LUA_GLOBALSINDEX
was removed. You must get the global environment from the registry.Function
luaL_register
is deprecated. UseluaL_setfuncs
so that your module does not create globals. (Modules are not expected to set global variables anymore.)The
osize
argument to the allocation function may not be zero when creating a new block, that is, whenptr
isNULL
(seelua_Alloc
). Use only the testptr == NULL
to check whether the block is new.luaL_typerror
was removed. Write your own version if you need it.Functions
lua_equal
andlua_lessthan
are deprecated. Use the newlua_compare
with appropriate options instead.Function
lua_objlen
was renamedlua_rawlen
.Macros to inject/project nn-default integer and unsigned types were deprecated, only the versions which return
lua_Integer
are supported. Any type-casting or sign checking should be done in the C implementation. (This list of functions isluaL_checkint
,luaL_optint
,luaL_checklong
,luaL_optlong``lua_pushunsigned
,lua_tounsigned
,lua_tounsignedx
,luaL_checkunsigned
,luaL_optunsigned
)Changes in the API which currently are not used in the
app/modules
files.Pseudoindex
LUA_ENVIRONINDEX
and functionslua_getfenv
/lua_setfenv
were removed, as C functions no longer have environments.Function
lua_cpcall
is deprecated. You can simply push the function withlua_pushcfunction
and call it withlua_pcall
.Function
lua_dump
has an extra parameter,strip
. Use 0 as the value of this parameter to get the old behavior.Continuation functions now receive as parameters what they needed to get through
lua_getctx
, solua_getctx
has been removed. Adapt your code accordingly.Function
lua_load
has an extra parameter,mode
. PassNULL
to simulate the old behavior.Function
lua_resume
has an extra parameter,from
. PassNULL
or the thread doing the call.Finalizers (
__gc
metamethods) for userdata are called in the reverse order that they were marked for finalization, not that they were created. (Most userdata are marked immediately after they are created.) Moreover, if the metatable does not have a__gc
field when set, the finalizer will not be called, even if it is set later.Functions to inject/project unsigned integers () were deprecated. Use their signed equivalents with a type cast.
The text was updated successfully, but these errors were encountered: