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