Page 1 of 1

Superloading and module-level local variables

Posted: Tue Mar 11, 2014 12:20 pm
by StarWeaver
Soo, I was just making a modlet to tweak the display of the chat/gamelogs, which requires changing some functions in mod/class/uiset/Minimalist.lua ... near the top of that file is:

Code: Select all

-- require require etc
module(..., package.seeall, class.inherit(UISet, TooltipsData))

local move_handle = {core.display.loadImage("/data/gfx/ui/move_handle.png"):glTexture()}

local frames_colors = {
	ok = {0.3, 0.6, 0.3},
	sustain = {0.6, 0.6, 0},
	cooldown = {0.6, 0, 0},
	disabled = {0.65, 0.65, 0.65},
}

-- Load the various shaders used to display resources
air_c = {0x92/255, 0xe5, 0xe8}
-- ...
The functions I'm overriding reference move_handle, and there appears to be no way to get at the original copy of that from inside the superload file; even an explicit

Code: Select all

local _M = loadPrevious(...)
local move_handle = _M.move_handle
dosen't work.

The best I can come up with is recreating the object:

Code: Select all

local _M = loadPrevious(...)
local move_handle = {core.display.loadImage("/data/gfx/ui/move_handle.png"):glTexture()}
Which I would guess is probably fine for this particular use, but seems like it would create the potential for unnecessary cross-version disharmony if any of these module locals are changed in the future.

Re: Superloading and module-level local variables

Posted: Tue Mar 11, 2014 3:17 pm
by Marson
Don't forget, with superload's loadPrevious() you aren't changing the function, you are just adding code to the beginning or the end. If you want to change the internal code of the function, you have to overwrite it. You can do that with overload—or you can use superload, but instead of loadPrevious(), you copy the function over and make the changes you need.

Re: Superloading and module-level local variables

Posted: Tue Mar 11, 2014 3:22 pm
by Doctornull
StarWeaver wrote:The best I can come up with is recreating the object:
(...)
Which I would guess is probably fine for this particular use, but seems like it would create the potential for unnecessary cross-version disharmony if any of these module locals are changed in the future.
Yep. File-scope 'local' variables are not visible outside that file itself. With superloading what you can do is gain access to the structures created as file-scope globals via '_M:...', but not file-scope locals.

@Marson - one can indeed augment or replace structures and functions, but not all of them.

Re: Superloading and module-level local variables

Posted: Tue Mar 11, 2014 3:48 pm
by Marson
I didn't phrase it correctly, but this is what I meant:

Let's say example.lua contains:

Code: Select all

function _M:strip(s)
    s = s:gsub("e", "")
    return s
end
If you create a /superload/example.lua:

Code: Select all

local _M = loadPrevious(...)
local base_strip = _M.strip

function _M:strip(s)
    -- you can put code here to modify "s"
    local base_return = base_strip(s)
    -- or you can put code here to modify "base_return"
    return (base_return)
end

return _M
but either way, all "e" characters from the initial input will be stripped out. If you want that to be "i" instead, you will need to copy the entire function over and change it that way.

Code: Select all

local _M = loadPrevious(...)

function _M:strip(s)
    s = s:gsub("i", "")
    return s
end

return _M
which is what I think people are calling superoverload.

Re: Superloading and module-level local variables

Posted: Tue Mar 11, 2014 3:58 pm
by darkgod
Accessing the local variables is possible if you can run inside a function that executes in its lexical scope.
To cut short the explanation you are lucky, you can!

You must hook on "UISet:Minimalist:Load" like that:

Code: Select all

class:bindHook("UISet:Minimalist:Load", function(self, data)
	local i = 1
	while true do
		local kk, vv = debug.getlocal(3, i)
		if not kk then break end
		if kk == "move_handle" then
			-- here vv is the value of the local "move_handle"
		end
		i = i + 1
	end
end

Re: Superloading and module-level local variables

Posted: Tue Mar 11, 2014 4:07 pm
by Doctornull
Marson wrote:which is what I think people are calling superoverload.
Hmm, I've never heard that term before.
darkgod wrote:Accessing the local variables is possible if you can run inside a function that executes in its lexical scope.
To cut short the explanation you are lucky, you can!
Holy cow that's awesome.

Re: Superloading and module-level local variables

Posted: Tue Mar 11, 2014 4:08 pm
by Marson
Ooh handy. Thanks DG!

Re: Superloading and module-level local variables

Posted: Tue Mar 11, 2014 5:08 pm
by darkgod
Oh and a warning, it uses the debug API which as you see is not exactly explicit; and it's also very slow.
Using it for init is fine, jsut dont do it 1000 times every frame :)

Re: Superloading and module-level local variables

Posted: Tue Mar 11, 2014 7:49 pm
by StarWeaver
Marson - the superload system dosen't actually do the 'before and after original function' thing for you, that's why the examples explicitly save the old function to something else and then call it; I chose not to do that right off the bat :3.

DG - That's interesting. It really seems that for superload to work as intended in all cases it should forward the module locals to the new file's namespace as well as the globals -- I mean, ideally, the execution environment in the superloaded file should be the same as that of the original file, right?

If that's not possible, how about hacking the interpreter to dump those locals into a _L object for the superload file?

Re: Superloading and module-level local variables

Posted: Tue Mar 11, 2014 8:23 pm
by darkgod
No, it's extremely rare that there are locals and even more locals of interrest

Re: Superloading and module-level local variables

Posted: Wed Mar 12, 2014 1:11 am
by HousePet
darkgod wrote:No, it's extremely rare that there are locals and even more locals of interrest
Lies!
Try superloading anything into the FoV stuff.

Re: Superloading and module-level local variables

Posted: Wed Sep 17, 2014 12:03 am
by Nagyhal
darkgod wrote: Accessing the local variables is possible if you can run inside a function that executes in its lexical scope.
To cut short the explanation you are lucky, you can!
This is so awesome it:

1. Deserves a bump
2. Is going in my one-day-to-be-released grimoire of DG Lua trickery. It's getting to be quite a collection!