It is currently March 28th, 2024, 5:04 pm

[BUG] LUA: loadstring() not working

Report bugs with the Rainmeter application and suggest features.
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm
Contact:

[BUG] LUA: loadstring() not working

Post by death.crafter »

loadstring is not detecting global variables in lua.

Try this:

Code: Select all

function Initialize()
	i=0
	loadstring("print(i+1)")()
end
I don't expect much, but is there an alternative in the meanwhile?
User avatar
Brian
Developer
Posts: 2673
Joined: November 24th, 2011, 1:42 am
Location: Utah

Re: [BUG] LUA: loadstring() not working

Post by Brian »

I think you have to do string concatenation for this to work since loadstring cannot access variables directly.

Code: Select all

function Initialize()
	i=0
	loadstring("print(" .. (i + 1) .. ")")()
end
If I'm not mistaken, loadstring declares a "chunk" of code to be executed later (or in this case, the trailing () calls the function).

Another option might be:

Code: Select all


function Initialize()
	loadstring("local i = 0; print(i + 1)")()
end
-Brian
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm
Contact:

Re: [BUG] LUA: loadstring() not working

Post by death.crafter »

Brian wrote: September 10th, 2021, 11:09 pm I think you have to do string concatenation for this to work since loadstring cannot access variables directly.

Code: Select all

function Initialize()
	i=0
	loadstring("print(" .. (i + 1) .. ")")()
end
If I'm not mistaken, loadstring declares a "chunk" of code to be executed later (or in this case, the trailing () calls the function).

Another option might be:

Code: Select all


function Initialize()
	loadstring("local i = 0; print(i + 1)")()
end
-Brian
No, actually it's not. It can access global variables, just not local.

Check out the execution here.


Also the lua documentation:
However, the two codes are not completely equivalent, because loadstring does not compile with lexical scoping. To see the difference, let us change the previous examples a little:

local i = 0
f = loadstring("i = i + 1")
g = function () i = i + 1 end

The g function manipulates the local i, as expected, but f manipulates a global i, because loadstring always compiles its strings in a global environment.

The most typical use of loadstring is to run external code, that is, pieces of code that come from outside your program. For instance, you may want to plot a function defined by the user; the user enters the function code and then you use loadstring to evaluate it. Note that loadstring expects a chunk, that is, statements. If you want to evaluate an expression, you must prefix it with return, so that you get a statement that returns the value of the given expression.
I think it's something in the compiler, because in the log it says, Attempt to do arithmetic on global i, a nil value, which it isn't.
User avatar
Brian
Developer
Posts: 2673
Joined: November 24th, 2011, 1:42 am
Location: Utah

Re: [BUG] LUA: loadstring() not working

Post by Brian »

death.crafter wrote: September 11th, 2021, 3:00 am No, actually it's not. It can access global variables, just not local.

Check out the execution here.
That online compiler uses Lua 5.3. Rainmeter uses Lua 5.1.5.
death.crafter wrote: September 11th, 2021, 3:00 am No, actually it's not. It can access global variables, just not local.

Check out the execution here.


Also the lua documentation:



I think it's something in the compiler, because in the log it says, Attempt to do arithmetic on global i, a nil value, which it isn't.
Hmm, not sure really. I suspect this has to do with each script is considered a non-global environment. Meaning you can load several scripts per skin (or in different skins) and they have their own environment....meaning multiple scripts can use the same function names/variables etc.

https://www.lua.org/pil/14.3.html

So, you could change environments and do something like this:

Code: Select all

function Initialize()
	i = 0
	local func = loadstring("print (i + 1)")
	setfenv(func, getfenv())
	func()

	--loadstring("local i = 0; print(i + 1)")()
end
I am sure loadstring solved some problem at one point, but it was removed from LUA after 5.1.

Honestly, this all seems like roundabout way of solving whatever problem is happening. If you must use loadstring, then I suggest using one of the examples that works.

-Brian
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm
Contact:

Re: [BUG] LUA: loadstring() not working

Post by death.crafter »

Brian wrote: September 11th, 2021, 4:23 am That online compiler uses Lua 5.3. Rainmeter uses Lua 5.1.5.
I just figured it out and was gonna ask, is a script measure really global?

So the answer is no.

Because this works:

Code: Select all

loadstring("i=1")()

function Initialize()
	loadstring("print(i+1)")()
end
And also, loadstring() isn't deprecated, it is just replaced by load().

P.S. shouldn't we upgrade to Lua 5.3? Ofc, I don't have any idea of the amount of work involved. So just asking. :D
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm
Contact:

Re: [BUG] LUA: loadstring() not working

Post by death.crafter »

Brian wrote: September 11th, 2021, 4:23 am

Code: Select all

function Initialize()
	i = 0
	local func = loadstring("print (i + 1)")
	setfenv(func, getfenv())
	func()

	--loadstring("local i = 0; print(i + 1)")()
end
But I can make a dostring() function using setfenv(). Thanks for the information.
User avatar
Brian
Developer
Posts: 2673
Joined: November 24th, 2011, 1:42 am
Location: Utah

Re: [BUG] LUA: loadstring() not working

Post by Brian »

death.crafter wrote: September 11th, 2021, 4:32 am P.S. shouldn't we upgrade to Lua 5.3? Ofc, I don't have any idea of the amount of work involved. So just asking. :D
We tried to upgrade a while back (2017), but it literally broke most existing scripts. The problem with LUA is that the authors often add or remove functions that break existing scripts. For most (non-Rainmeter) LUA users, upgrading a script is easy since it's not like these breaking changes happen all that often.

For Rainmeter, the problem is we have tens of thousands of skins out there. Quite a few of them use LUA scripts. If all the sudden those skins no longer work correctly, people either complain to us that something is broken, or they stay on a old version of Rainmeter....or worse, they stop using Rainmeter altogether.

We will probably leave LUA at 5.1.5.

However, we open to running different versions of LUA simultaneously if someone wants to submit the changes for it. If it is possible. :oops:

-Brian
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm
Contact:

Re: [BUG] LUA: loadstring() not working

Post by death.crafter »

Brian wrote: September 11th, 2021, 4:50 am We tried to upgrade a while back (2017), but it literally broke most existing scripts. The problem with LUA is that the authors often add or remove functions that break existing scripts. For most (non-Rainmeter) LUA users, upgrading a script is easy since it's not like these breaking changes happen all that often.

For Rainmeter, the problem is we have tens of thousands of skins out there. Quite a few of them use LUA scripts. If all the sudden those skins no longer work correctly, people either complain to us that something is broken, or they stay on a old version of Rainmeter....or worse, they stop using Rainmeter altogether.

We will probably leave LUA at 5.1.5.

However, we open to running different versions of LUA simultaneously if someone wants to submit the changes for it. If it is possible. :oops:

-Brian
Ohh I see. Backwards compatibility holds back Rainmeter a lot. :confused:
Wish I was a pro at C++ like you guys. I would have looked into it. I kind of have a fetish for latest things :oops:
User avatar
SilverAzide
Rainmeter Sage
Posts: 2588
Joined: March 23rd, 2015, 5:26 pm
Contact:

Re: [BUG] LUA: loadstring() not working

Post by SilverAzide »

death.crafter wrote: September 11th, 2021, 5:09 am Ohh I see. Backwards compatibility holds back Rainmeter a lot. :confused:
Well, I wouldn't exactly say backwards compatibility "holds back Rainmeter a lot"; it's more like: backwards compatibility "prevents a firehose of whining and screaming on the forums and DA and every other place about 'your skin is broken!' or 'Rainmeter doesn't work!' or 'you guys suck!' or etc etc..."

If you want to experience the joy of breaking changes, just look at the 10,000 identical postings on some variation of "my weather skin stopped working!" when TWC deprecated their WXData feed.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: [BUG] LUA: loadstring() not working

Post by jsmorley »

Backwards compatibility is the single best thing we ever did, and continue to do... It is "Rule 1". We simply will never orphan the hundreds of thousands of existing skins out there for download, many of which are no longer even supported by the original author. Any skin written for Rainmeter 1.0 will still work exactly as expected on Rainmeter 4.5.0.
Post Reply