neptools

Modding tools to Neptunia games
git clone https://git.neptards.moe/neptards/neptools.git
Log | Files | Refs | Submodules | README | LICENSE

builder.lua (2308B)


      1 local setfenv, setmetatable, typename, match, gsub, format, ipairs, error =
      2   setfenv, setmetatable, typename, string.match, string.gsub, string.format, ipairs, error
      3 assert(setfenv, "no setfenv") -- will fail on plain lua 5.2+
      4 
      5 local get_ctx = neptools.item.get_context
      6 local get_children = neptools.item_with_children.get_children
      7 
      8 local helpers = {}
      9 -- lazy load table
     10 -- When this script runs, only items and item_with_children is registered.
     11 -- We would need to run this script at the very end of registration phase, but
     12 -- that would fuck up inheritance...
     13 local function gen_helpers(tbl, ns)
     14   for k,v in pairs(ns) do
     15     if match(k, "_item$") then
     16       tbl[gsub(k, "_item$", "")] = v.new
     17     end
     18   end
     19 end
     20 
     21 local function get_helpers(typename)
     22   local tbl = helpers[typename]
     23   if tbl then return tbl end
     24 
     25   tbl = {}
     26   gen_helpers(tbl, neptools)
     27   if typename == "neptools.stcm.file" then
     28     gen_helpers(tbl, neptools.stcm)
     29     tbl.call = tbl.instruction -- alias
     30   elseif typename == "neptools.stsc.file" then
     31     gen_helpers(tbl, neptools.stsc)
     32     function tbl.instruction(ctx, opcode, ...)
     33       return neptools.stsc.instruction_item[ctx.flavor][opcode].
     34         new(ctx, opcode, ...)
     35     end
     36   else
     37     error("unknown type "..typename)
     38   end
     39 
     40   helpers[typename] = tbl
     41   return tbl
     42 end
     43 
     44 local function build(item, fun)
     45   local get_label = neptools.context.get_or_create_dummy_label
     46   local create_label = neptools.context.create_or_set_label
     47 
     48   local ctx = get_ctx(item)
     49   local children = get_children(item)
     50   local labels = {}
     51   local function defer_label(name, offs)
     52     labels[#labels+1] = { name, offs or 0 }
     53   end
     54 
     55   local function add(item)
     56     children:push_back(item)
     57     for i,v in ipairs(labels) do
     58       create_label(ctx, v[1], item, v[2])
     59       labels[i] = nil
     60     end
     61     return item
     62   end
     63 
     64   local tbl = {
     65     label = defer_label,
     66     l = function(n) return get_label(ctx, n) end,
     67     add = add,
     68     __index = _G,
     69     __newindex = error,
     70   }
     71 
     72   -- helpers
     73   for k,v in pairs(get_helpers(typename(ctx))) do
     74     tbl[k] = function(...) return add(v(ctx, ...)) end
     75   end
     76 
     77   setfenv(fun, setmetatable(tbl, tbl))
     78   fun()
     79   if labels[1] then
     80     error(format("label %q after last item", labels[1][1]))
     81   end
     82   if ctx == item then ctx:fixup() end -- todo
     83   return ctx
     84 end
     85 
     86 return build