On Sat, Sep 11, 2021 at 8:15 AM Philippe Verdy wrote:
A local <const> variable is not necessary initialized with a simple constant value, it may be initialized by the value of a complex _expression_ that needs to be evaluated only once, and its value stored somewhere.
Imagine you declare thousands of such local <const> variables
Please read a post attentively before answering.
I'm talking ONLY about local <const> variables initialized by a simple value (number or string).
Only these constants should not count in local variables quota.
Although some expressions are evaluated by Lua at compile time (for example, arithmetic on number literals), if you assign arbitrary _expression_ to unused constant, Lua may not optimize it completely:
local UNUSED <const> = "aaaaa".."bbbbb"
I agree: this can be evaluated at compile-time
UNUSED is never used in the code, but both strings "aaaaa" and "bbbbb" are present in the bytecode and in Lua VM memory. And CONCAT instruction is always executed.
So, there is no benefit here (at least, in the current implementation of Lua).
That's why I consider only local <const> variables initialized by a simple value.
Now imagine the compiler accepts thousands of such "local <const>" variable declarations in a function body. It will not know when parsing them if these variables are used or not: it will know that only after parsing the whole function body.
What does "not know when parsing them" mean? The whole Lua source (including all constant definitions) must always be parsed :-)
Not computable at compile-time but at runtime: e.g. calling a function, e.g.:
local sqrt2 <const> = math.sqrt(2)
This cannot be precomputed if "math" is not a constant bound to the standard library but is a normal variable; the compiler only knows that this must be a table having a key "sqrt" that can be used as a callable function. Which function will be used may not be known at compile time but at run-time.
If a local <const> variable is initialized with a simple value, it will never occupy a VM register independently of whether the constant is used or unused in the code.
So, the compiler can set the flag "this local <const> variable should not be counted in local variables quota" while parsing the line where the constant is defined, there is no need to parse the whole function body.
A local <const> is not necessarily "constant", its actual value may vary at run-time but will be computed only once, where the variable is declared. Then the variable must not change in the rest of its scope: the parser will ensure that it is not reassigned, and can infer optimisations (such as not allocating any register). Basically the <const> is just a helper for programmers, that avoids reassigning variables that should be kept in its scope. It's a protection for maintenance and refactoring of existing code in large function bodies that changes often.
But the compiler should generate exactly the same thing even when you discard the <const>: it can also make the same optimizations, including discarding unused variables. I see no real benefit of <const> declarations.