JariKCoding / CoDLuaDecompiler

Call of Duty Lua (HavokScript & LuaJit) Decompiler
MIT License
52 stars 14 forks source link

Problem with a table of functions defined within a table definition #11

Open Jake-NotTheMuss opened 2 years ago

Jake-NotTheMuss commented 2 years ago

Issue

There seems to be a decompiler bug that I noticed in the file lua.Lobby.Common.LobbyCore. In this file, a table is defined like the following:

Lobby = {
    ProcessTree = nil,
    Navigation = {},
    Core = {},
    HANDLER_TYPE_FWD = 1,
    HANDLER_TYPE_BACK = 2,
    Core = function ( fromTarget, toTarget, handlerType, handler )
        if Lobby.Navigation[fromTarget.name] == nil then
            Lobby.Navigation[fromTarget.name] = {}
        end
        if Lobby.Navigation[fromTarget.name][handlerType] == nil then
            Lobby.Navigation[fromTarget.name][handlerType] = {}
        end
        Lobby.Navigation[fromTarget.name][handlerType][toTarget.name] = handler
    end,
    Core = function ( fromTarget, toTarget, handler )
        local handlerType = Lobby.HANDLER_TYPE_FWD
        if Lobby.Navigation[fromTarget.name] ~= nil and Lobby.Navigation[fromTarget.name][handlerType] ~= nil and Lobby.Navigation[fromTarget.name][handlerType][toTarget.name] ~= nil then
            error( "LobbyVM: A forward handler already exists from '" .. fromTarget.name .. " to " .. toTarget.name )
        end
        Lobby.Core.AddHandler( fromTarget, toTarget, handlerType, handler )
    end,

In this file, 6 functions are defined within the Lobby.Core table:

Lobby.Core.AddHandler = function(fromTarget, toTarget, handlerType, handler)
Lobby.Core.AddProcessForward = function(fromTarget, toTarget, handler)
Lobby.Core.AddProcessBack = function(fromTarget, toTarget, handler)
Lobby.Core.GetForwardProcessFunc = function(fromTarget, toTarget)
Lobby.Core.GetBackProcessFunc = function(fromTarget)
Lobby.Core.GetMainModeStr = function(mainMode)

In the decompilation, however, these functions are simply named "Core", overwriting the Core previously defined. Each function is simply defined in the form Core = function() ....

I also have a question about something within this same file that I can't find any answers to online.

Question

In the function Lobby.Core.GetBackProcessFunc(), there is a call to pairs():

if backNavTable ~= nil then
    local f5_local0, f5_local1, f5_local2 = pairs( backNavTable )
    local backMenuName, handler = f5_local0( f5_local1, f5_local2 )
    if backMenuName ~= nil then
        f5_local2 = backMenuName
        return LobbyData:UITargetFromName( backMenuName ), handler
    end
end

This snippet is taken from a decompilation of the beta version of the script. I am using the beta version to highlight the fact that certain variables do not have names and are therefore decompiler-generated. The current version of the same script decompiles the same way, resulting in an identical result, only without any variable names.

What I'm trying to figure out is what this function should look like in source. Since the 3 variables assigned after calling pairs() do not have names, in the source, the call to pairs() was not assigned immediately. It was part of a more complex expression, than assigned to the variables backMenuName and handler.

Having an extra parenthesis after the pairs() call would then call the 1st return value of pairs(), like the following:

local backMenuName, handler = pairs(backNavTable)()

But what I am confused about is how the 2nd and 3rd return value of pairs() were used as arguments to the second call. Could you enlighten me on this problem?

UPDATE 7/25/22: It seems this is caused by a for loop which returns or breaks unconditionally. I don't know if it's the compiler optimizing away the loop, or if its the decompiler not recognizing it as a loop. In any case, the source would probably looked like the following:

for backMenuName, handler in pairs(backNavTable) do
    return LobbyData:UITargetFromName(backMenuName), handler
end