Checking Lua scripts against Dwarf Fortress data structures

June 10, 2016

Dwarf Fortress Remote server contains a lot of Lua code, and now that I’m adding support for more DF versions, I need to make sure all my code is updated as DF data structures change. I could probably just diff data structure definition files, but I’d like to have a less time consuming and more reliable solution.

So I started to work on a tool that automatically checks Lua scripts and shows access to wrong fields, incorrect assignments and so on – things that a compiler would show errors for, were Lua a statically typed language.

Here it is: https://github.com/mifki/df-luacheck

It’s a work in progress, with a lot of unsupported things, including require statements and built-in DFHack library functions, so it can’t be used to check real scripts yet, but I’ll improve it until it can check all of the DF Remote code and show what needs to be fixed for 0.42. Some examples of what it can do below.

function test(unitid)
    local ret = {}

    for i,unit in ipairs(df.global.world.units.active) do
        if unit.civ_id == df.global.ui.civ_id and unit.flags1.tame and not unit.flags1.dead and not unit.flags1.forest then
            local work = (unit.profession == df.profession.TRAINED_WAR or unit.profession == df.profession.TRAINED_HUNT)
            local geld = unit.flags3.geld

            -- ...  
        end
    end

    return ret
end

test(1)

---------------------------
6: ERROR value TRAINED_HUNT does not exist in enum df.profession
6: ERROR type of operand df.profession.TRAINED_HUNT is unknown, assuming the result is bool
7: ERROR field geld does not exist in unit.flags3 of type df.unit_flags3
7: ERROR type of expression is unknown unit.flags3.geld

function test(bldid)
    local bld

    if bldid then
        bld = df.building.find(bldid)
    else
        bld = df.global.world.selected_bld
    end    

    bld.owner_id = df.global.world.units.active[0]
end

test(1)

---------------------------
7: ERROR field selected_bld does not exist in df.global.world of type df ou acheter du vrai viagra.world
7: ERROR type of expression is unknown df.global.world.selected_bld
10: ERROR assigning df.global.world.units.active[0] of type df.unit to bld.owner_id of type number



hljs.initHighlightingOnLoad();