-- BindingsProcessor.lua
-- Implements additional processing that is done while generating the Lua bindings
local access = {public = 0, protected = 1, private = 2}
--- Defines classes that have a custom manual Push() implementation and should not generate the automatic one
-- Map of classname -> true
local g_HasCustomPushImplementation =
{
cEntity = true
}
function parser_hook(s)
local container = classContainer.curr -- get the current container
-- process access-specifying labels (public, private, etc)
do
local b, e, label = string.find(s, "^%s*(%w*)%s*:[^:]") -- we need to check for [^:], otherwise it would match 'namespace::type'
if b then
-- found a label, get the new access value from the global 'access' table
if access[label] then
container.curr_member_access = access[label]
end -- else ?
return strsub(s, e) -- normally we would use 'e+1', but we need to preserve the [^:]
end
end
end
--- Outputs the helper files supplementing the cLuaState class
-- Writes:
-- LuaState_Declaration.inc
-- LuaState_Implementation.cpp
-- LuaState_Typedefs.inc
local function OutputLuaStateHelpers(a_Package)
-- Collect all class types from ToLua:
local types = {}
for idx, item in ipairs(a_Package) do
local mt = getmetatable(item) or {}
if (mt.classtype == "class") then
table.insert(types, {name = item.name, lname = item.lname})
end
end
table.sort(types,
function(a_Item1, a_Item2)
return (a_Item1.name:lower() < a_Item2.name:lower())
end
)
-- Output the typedefs:
do
local f = assert(io.open("LuaState_Typedefs.inc", "w"))
f:write("\n// LuaState_Typedefs.inc\n\n// This file is generated along with the Lua bindings by ToLua. Do not edit manually, do not commit to repo.\n")
f:write("// Provides a forward declaration and a typedef for a pointer to each class exported to the Lua API.\n")
f:write("\n\n\n\n\n")
for _, item in ipairs(types) do
if not(item.name:match(".*<.*")) then -- Skip templates altogether
-- Classes start with a "c", everything else is a struct:
if (item.name:sub(1, 1) == "c") then
f:write("class " .. item.name .. ";\n")
else
f:write("struct " .. item.name .. ";\n")
end
end
end
f:write("\n\n\n\n\n")
for _, item in ipairs(types) do
f:write("typedef " .. item.name .. " * Ptr" .. item.lname .. ";\n")
end
f:write("\n\n\n\n\n")
f:close()
end
-- Output the Push() and GetStackValue() function declarations:
do
local f = assert(io.open("LuaState_Declaration.inc", "w"))
f:write("\n// LuaState_Declaration.inc\n\n// This file is generated along with the Lua bindings by ToLua. Do not edit manually, do not commit to repo.\n")
f:write("// Implements a Push() and GetStackValue() function for each class exported to the Lua API.\n")
f:write("// This file expects to be included form inside the cLuaState class definition\n")
f:write("\n\n\n\n\n")
for _, item in ipairs(types) do
f:write("void Push(" .. item.name .. " * a_Value);\n")
end
for _, item in ipairs(types) do
f:write("void GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal);\n")
end
f:write("\n\n\n\n\n")
f:close()
end
-- Output the Push() and GetStackValue() function implementations:
do
local f = assert(io.open("LuaState_Implementation.cpp", "w"))
f:write("\n// LuaState_Implementation.cpp\n\n// This file is generated along with the Lua bindings by ToLua. Do not edit manually, do not commit to repo.\n")
f:write("// Implements a Push() and GetStackValue() function for each class exported to the Lua API.\n")
f:write("// This file expects to be compiled as a separate translation unit\n")
f:write("\n\n\n\n\n")
f:write("#include \"Globals.h\"\n#include \"LuaState.h\"\n#include \"tolua++/include/tolua++.h\"\n")
f:write("\n\n\n\n\n")
for _, item in ipairs(types) do
if not(g_HasCustomPushImplementation[item.name]) then
f:write("void cLuaState::Push(" .. item.name .. " * a_Value)\n{\n\tASSERT(IsValid());\n")
f:write("\ttolua_pushusertype(m_LuaState, a_Value, \"" .. item.name .. "\");\n");
f:write("\tm_NumCurrentFunctionArgs += 1;\n")
f:write("}\n\n\n\n\n\n")
end
end
for _, item in ipairs(types) do
f:write("void cLuaState::GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal)\n{\n\tASSERT(IsValid());\n")
f:write("\tif (lua_isnil(m_LuaState, a_StackPos))\n\t{\n")
f:write("\t a_ReturnedVal = nullptr;\n")
f:write("\t return;\n\t}\n")
f:write("\ttolua_Error err;\n")
f:write("\tif (tolua_isusertype(m_LuaState, a_StackPos, \"" .. item.name .. "\", false, &err))\n")
f:write("\t{\n")
f:write("\t a_ReturnedVal = *(reinterpret_cast<" .. item.name .. " **>(lua_touserdata(m_LuaState, a_StackPos)));\n")
f:write("\t}\n")
f:write("}\n\n\n\n\n\n")
end
f:close()
end
end
function pre_output_hook(a_Package)
OutputLuaStateHelpers(a_Package)
end
function post_output_hook()
print("Bindings have been generated.")
end