bgfx/scripts/codegen.lua

769 lines
19 KiB
Lua
Raw Normal View History

2019-02-27 12:49:28 +03:00
-- Copyright 2019 云风 https://github.com/cloudwu . All rights reserved.
-- License (the same with bgfx) : https://github.com/bkaradzic/bgfx/blob/master/LICENSE
local codegen = {}
2019-03-10 09:40:43 +03:00
local NAMEALIGN = 20
local function namealign(name, align)
align = align or NAMEALIGN
return string.rep(" ", align - #name)
end
2019-02-27 12:49:28 +03:00
local function camelcase_to_underscorecase(name)
local tmp = {}
for v in name:gmatch "[%u%d]+%l*" do
tmp[#tmp+1] = v:lower()
end
return table.concat(tmp, "_")
end
local function convert_funcname(name)
name = name:gsub("^%l", string.upper) -- Change to upper CamlCase
return camelcase_to_underscorecase(name)
end
2019-03-10 09:40:43 +03:00
local function convert_arg(all_types, arg, namespace)
local fulltype, array = arg.fulltype:match "(.-)%s*(%[%s*[%d%a_:]*%s*%])"
if array then
arg.fulltype = fulltype
arg.array = array
local enum, value = array:match "%[%s*([%a%d]+)::([%a%d]+)%]"
if enum then
local typedef = all_types[ enum .. "::Enum" ]
if typedef == nil then
error ("Unknown Enum " .. enum)
end
arg.carray = "[BGFX_" .. camelcase_to_underscorecase(enum):upper() .. "_" .. value:upper() .. "]"
end
end
2019-02-27 12:49:28 +03:00
local t, postfix = arg.fulltype:match "(%a[%a%d_:]*)%s*([*&]+)%s*$"
if t then
arg.type = t
if postfix == "&" then
arg.ref = true
end
else
2019-03-10 09:40:43 +03:00
local prefix, t = arg.fulltype:match "^%s*(%a+)%s+(%S+)"
if prefix then
arg.type = t
else
arg.type = arg.fulltype
end
end
local ctype
local substruct = namespace.substruct
if substruct then
ctype = substruct[arg.type]
2019-02-27 12:49:28 +03:00
end
if not ctype then
2019-03-10 09:40:43 +03:00
ctype = all_types[arg.type]
end
if not ctype then
error ("Undefined type " .. arg.fulltype .. " in " .. namespace.name)
2019-02-27 12:49:28 +03:00
end
arg.ctype = arg.fulltype:gsub(arg.type, ctype.cname):gsub("&", "*")
if ctype.cname ~= arg.type then
arg.cpptype = arg.fulltype:gsub(arg.type, "bgfx::"..arg.type)
else
arg.cpptype = arg.fulltype
end
if arg.ref then
arg.ptype = arg.cpptype:gsub("&", "*")
end
end
local function alternative_name(name)
if name:sub(1,1) == "_" then
return name:sub(2)
else
return name .. "_"
end
end
local function gen_arg_conversion(all_types, arg)
if arg.ctype == arg.fulltype then
-- do not need conversion
return
end
local ctype = all_types[arg.type]
if ctype.handle and arg.type == arg.fulltype then
local aname = alternative_name(arg.name)
arg.aname = aname .. ".cpp"
2019-03-10 09:40:43 +03:00
arg.aname_cpp2c = aname .. ".c"
2019-02-27 12:49:28 +03:00
arg.conversion = string.format(
"union { %s c; bgfx::%s cpp; } %s = { %s };" ,
ctype.cname, arg.type, aname, arg.name)
2019-03-10 09:40:43 +03:00
arg.conversion_back = string.format(
"union { bgfx::%s cpp; %s c; } %s = { %s };" ,
arg.type, ctype.cname, aname, arg.name)
2019-02-27 12:49:28 +03:00
elseif arg.ref then
if ctype.cname == arg.type then
arg.aname = "*" .. arg.name
2019-03-10 09:40:43 +03:00
arg.aname_cpp2c = "&" .. arg.name
2019-02-27 12:49:28 +03:00
elseif arg.out and ctype.enum then
local aname = alternative_name(arg.name)
local cpptype = arg.cpptype:match "(.-)%s*&" -- remove &
2019-03-10 09:40:43 +03:00
local c99type = arg.ctype:match "(.-)%s*%*" -- remove *
2019-02-27 12:49:28 +03:00
arg.aname = aname
2019-03-10 09:40:43 +03:00
arg.aname_cpp2c = "&" .. aname
2019-02-27 12:49:28 +03:00
arg.conversion = string.format("%s %s;", cpptype, aname)
2019-03-10 09:40:43 +03:00
arg.conversion_back = string.format("%s %s;", c99type, aname);
2019-02-27 12:49:28 +03:00
arg.out_conversion = string.format("*%s = (%s)%s;", arg.name, ctype.cname, aname)
2019-03-10 09:40:43 +03:00
arg.out_conversion_back = string.format("%s = (%s)%s;", arg.name, c99type, aname)
2019-02-27 12:49:28 +03:00
else
arg.aname = alternative_name(arg.name)
2019-03-10 09:40:43 +03:00
arg.aname_cpp2c = string.format("(%s)&%s" , arg.ctype , arg.name)
2019-02-27 12:49:28 +03:00
arg.conversion = string.format(
"%s %s = *(%s)%s;",
arg.cpptype, arg.aname, arg.ptype, arg.name)
end
else
2019-03-10 09:40:43 +03:00
local cpptype = arg.cpptype
local ctype = arg.ctype
if arg.array then
cpptype = cpptype .. "*"
ctype = ctype .. "*"
end
2019-02-27 12:49:28 +03:00
arg.aname = string.format(
"(%s)%s",
2019-03-10 09:40:43 +03:00
cpptype, arg.name)
arg.aname_cpp2c = string.format(
"(%s)%s",
ctype, arg.name)
2019-02-27 12:49:28 +03:00
end
end
local function gen_ret_conversion(all_types, func)
local postfix = { func.vararg and "va_end(argList);" }
2019-03-10 09:40:43 +03:00
local postfix_cpp2c = { postfix[1] }
2019-02-27 12:49:28 +03:00
func.ret_postfix = postfix
2019-03-10 09:40:43 +03:00
func.ret_postfix_cpp2c = postfix_cpp2c
2019-02-27 12:49:28 +03:00
for _, arg in ipairs(func.args) do
if arg.out_conversion then
postfix[#postfix+1] = arg.out_conversion
2019-03-10 09:40:43 +03:00
postfix_cpp2c[#postfix_cpp2c+1] = arg.out_conversion_back
2019-02-27 12:49:28 +03:00
end
end
local ctype = all_types[func.ret.type]
if ctype.handle then
func.ret_conversion = string.format(
"union { %s c; bgfx::%s cpp; } handle_ret;" ,
2019-03-10 09:40:43 +03:00
ctype.cname, ctype.name)
func.ret_conversion_cpp2c = string.format(
"union { bgfx::%s cpp; %s c; } handle_ret;" ,
ctype.name, ctype.cname)
2019-02-27 12:49:28 +03:00
func.ret_prefix = "handle_ret.cpp = "
2019-03-10 09:40:43 +03:00
func.ret_prefix_cpp2c = "handle_ret.c = "
2019-02-27 12:49:28 +03:00
postfix[#postfix+1] = "return handle_ret.c;"
2019-03-10 09:40:43 +03:00
postfix_cpp2c[#postfix_cpp2c+1] = "return handle_ret.cpp;"
2019-02-27 12:49:28 +03:00
elseif func.ret.fulltype ~= "void" then
2019-03-10 09:40:43 +03:00
local ctype_conversion = ctype.name == ctype.cname and "" or ("(" .. func.ret.ctype .. ")")
local conversion_back = ctype.name == ctype.cname and "" or ("(" .. func.ret.cpptype .. ")")
2019-02-27 12:49:28 +03:00
if #postfix > 0 then
func.ret_prefix = string.format("%s retValue = %s", func.ret.ctype , ctype_conversion)
2019-03-10 09:40:43 +03:00
func.ret_prefix_cpp2c = string.format("%s retValue = %s", func.ret.cpptype , conversion_back)
local ret = "return retValue;"
postfix[#postfix+1] = ret
postfix_cpp2c[#postfix_cpp2c+1] = ret
2019-02-27 12:49:28 +03:00
else
func.ret_prefix = string.format("return %s", ctype_conversion)
2019-03-10 09:40:43 +03:00
func.ret_prefix_cpp2c = string.format("return %s", conversion_back)
2019-02-27 12:49:28 +03:00
end
end
end
2019-03-10 09:40:43 +03:00
local function convert_vararg(v)
if v.vararg then
local args = v.args
local vararg = {
name = "",
fulltype = "...",
type = "...",
ctype = "...",
aname = "argList",
conversion = string.format(
"va_list argList;\n\tva_start(argList, %s);",
args[#args].name),
}
args[#args + 1] = vararg
v.alter_name = v.vararg
end
end
2019-02-27 12:49:28 +03:00
function codegen.nameconversion(all_types, all_funcs)
2019-03-10 09:40:43 +03:00
for _,v in ipairs(all_types) do
local name = v.name
local cname = v.cname
if cname == nil then
if name:match "^%u" then
cname = camelcase_to_underscorecase(name)
else
v.cname = name
end
end
if cname then
if v.namespace then
cname = camelcase_to_underscorecase(v.namespace) .. "_" .. cname
end
v.cname = "bgfx_".. cname .. "_t"
2019-02-27 12:49:28 +03:00
end
if v.enum then
2019-03-10 09:40:43 +03:00
v.name = v.name .. "::Enum"
2019-02-27 12:49:28 +03:00
end
end
2019-03-10 09:40:43 +03:00
-- make index
for _,v in ipairs(all_types) do
if not v.namespace then
if all_types[v.name] then
error ("Duplicate type " .. v.name)
end
all_types[v.name] = v
end
end
-- make sub struct index
for _,v in ipairs(all_types) do
if v.namespace then
local super = all_types[v.namespace]
if not super then
error ("Define " .. v.namespace .. " first")
end
local substruct = super.substruct
if not substruct then
substruct = {}
super.substruct = substruct
end
if substruct[v.name] then
error ( "Duplicate sub struct " .. v.name .. " in " .. v.namespace)
end
substruct[#substruct+1] = v
substruct[v.name] = v
end
end
for _,v in ipairs(all_types) do
if v.struct then
for _, item in ipairs(v.struct) do
convert_arg(all_types, item, v)
end
elseif v.args then
-- funcptr
for _, arg in ipairs(v.args) do
convert_arg(all_types, arg, v)
end
convert_vararg(v)
convert_arg(all_types, v.ret, v)
end
2019-02-27 12:49:28 +03:00
end
2019-03-10 09:40:43 +03:00
local funcs = {}
local funcs_conly = {}
local funcs_alter = {}
2019-02-27 12:49:28 +03:00
for _,v in ipairs(all_funcs) do
if v.cname == nil then
v.cname = convert_funcname(v.name)
end
if v.class then
v.cname = convert_funcname(v.class) .. "_" .. v.cname
2019-03-10 09:40:43 +03:00
local classtype = all_types[v.class]
if classtype then
local methods = classtype.methods
if not methods then
methods = {}
classtype.methods = methods
end
methods[#methods+1] = v
end
elseif not v.conly then
funcs[v.name] = v
2019-02-27 12:49:28 +03:00
end
2019-03-10 09:40:43 +03:00
if v.conly then
table.insert(funcs_conly, v)
end
2019-02-27 12:49:28 +03:00
for _, arg in ipairs(v.args) do
2019-03-10 09:40:43 +03:00
convert_arg(all_types, arg, v)
2019-02-27 12:49:28 +03:00
gen_arg_conversion(all_types, arg)
end
2019-03-10 09:40:43 +03:00
convert_vararg(v)
if v.alter_name then
funcs_alter[#funcs_alter+1] = v
2019-02-27 12:49:28 +03:00
end
2019-03-10 09:40:43 +03:00
convert_arg(all_types, v.ret, v)
2019-02-27 12:49:28 +03:00
gen_ret_conversion(all_types, v)
2019-03-10 09:40:43 +03:00
local namespace = v.class
if namespace then
local classname = namespace
2019-02-27 12:49:28 +03:00
if v.const then
classname = "const " .. classname
end
local classtype = { fulltype = classname .. "*" }
2019-03-10 09:40:43 +03:00
convert_arg(all_types, classtype, v)
2019-02-27 12:49:28 +03:00
v.this = classtype.ctype .. " _this"
v.this_conversion = string.format( "%s This = (%s)_this;", classtype.cpptype, classtype.cpptype)
2019-03-10 09:40:43 +03:00
v.this_to_c = string.format("(%s)this", classtype.ctype)
end
end
for _, v in ipairs(funcs_conly) do
local func = funcs[v.name]
if func then
func.multicfunc = func.multicfunc or { func.cname }
table.insert(func.multicfunc, v.cname)
2019-02-27 12:49:28 +03:00
end
end
2019-03-10 09:40:43 +03:00
for _, v in ipairs(funcs_alter) do
local func = funcs[v.alter_name]
v.alter_cname = func.cname
end
2019-02-27 12:49:28 +03:00
end
local function lines(tbl)
2019-03-10 09:40:43 +03:00
if not tbl or #tbl == 0 then
2019-02-27 12:49:28 +03:00
return "//EMPTYLINE"
else
return table.concat(tbl, "\n\t")
end
end
local function remove_emptylines(txt)
return (txt:gsub("\t//EMPTYLINE\n", ""))
end
local function codetemp(func)
local conversion = {}
2019-03-10 09:40:43 +03:00
local conversion_c2cpp = {}
2019-02-27 12:49:28 +03:00
local args = {}
2019-03-10 09:40:43 +03:00
local cargs = {}
local callargs_conversion = {}
local callargs_conversion_back = {}
2019-02-27 12:49:28 +03:00
local callargs = {}
local cppfunc
2019-03-10 09:40:43 +03:00
local classname
2019-02-27 12:49:28 +03:00
if func.class then
-- It's a member function
2019-03-10 09:40:43 +03:00
cargs[1] = func.this
2019-02-27 12:49:28 +03:00
conversion[1] = func.this_conversion
cppfunc = "This->" .. func.name
2019-03-10 09:40:43 +03:00
callargs[1] = "_this"
callargs_conversion_back[1] = func.this_to_c
classname = func.class .. "::"
2019-02-27 12:49:28 +03:00
else
2019-03-10 09:40:43 +03:00
cppfunc = "bgfx::" .. tostring(func.alter_name or func.name)
classname = ""
2019-02-27 12:49:28 +03:00
end
for _, arg in ipairs(func.args) do
conversion[#conversion+1] = arg.conversion
2019-03-10 09:40:43 +03:00
conversion_c2cpp[#conversion_c2cpp+1] = arg.conversion_back
local cname = arg.ctype .. " " .. arg.name
if arg.array then
cname = cname .. (arg.carray or arg.array)
end
local name = arg.fulltype .. " " .. arg.name
if arg.array then
name = name .. arg.array
end
if arg.default then
name = name .. " = " .. arg.default
end
cargs[#cargs+1] = cname
args[#args+1] = name
callargs_conversion[#callargs_conversion+1] = arg.aname or arg.name
callargs_conversion_back[#callargs_conversion_back+1] = arg.aname_cpp2c or arg.name
callargs[#callargs+1] = arg.name
2019-02-27 12:49:28 +03:00
end
conversion[#conversion+1] = func.ret_conversion
2019-03-10 09:40:43 +03:00
conversion_c2cpp[#conversion_c2cpp+1] = func.ret_conversion_cpp2c
local ARGS
local args_n = #args
if args_n == 0 then
ARGS = ""
elseif args_n == 1 then
ARGS = args[1]
else
ARGS = "\n\t " .. table.concat(args, "\n\t, ") .. "\n\t"
end
local preret_c2c
local postret_c2c = {}
local conversion_c2c = {}
local callfunc_c2c
if func.vararg then
postret_c2c[1] = "va_end(argList);"
local vararg = func.args[#func.args]
callargs[#callargs] = vararg.aname
callargs_conversion_back[#callargs_conversion_back] = vararg.aname
conversion_c2c[1] = vararg.conversion
conversion_c2cpp[1] = vararg.conversion
if func.ret.fulltype == "void" then
preret_c2c = ""
else
preret_c2c = func.ret.ctype .. " retValue = "
postret_c2c[#postret_c2c+1] = "return retValue;"
end
callfunc_c2c = func.alter_cname or func.cname
else
if func.ret.fulltype == "void" then
preret_c2c = ""
else
preret_c2c = "return "
end
callfunc_c2c = func.cname
end
2019-02-27 12:49:28 +03:00
return {
2019-03-10 09:40:43 +03:00
RET = func.ret.fulltype,
CRET = func.ret.ctype,
CFUNCNAME = func.cname,
FUNCNAME = func.name,
CARGS = table.concat(cargs, ", "),
CPPARGS = table.concat(args, ", "),
ARGS = ARGS,
2019-02-27 12:49:28 +03:00
CONVERSION = lines(conversion),
2019-03-10 09:40:43 +03:00
CONVERSIONCTOC = lines(conversion_c2c),
CONVERSIONCTOCPP = lines(conversion_c2cpp),
2019-02-27 12:49:28 +03:00
PRERET = func.ret_prefix or "",
2019-03-10 09:40:43 +03:00
PRERETCPPTOC = func.ret_prefix_cpp2c or "",
2019-02-27 12:49:28 +03:00
CPPFUNC = cppfunc,
2019-03-10 09:40:43 +03:00
CALLFUNCCTOC = callfunc_c2c,
CALLARGSCTOCPP = table.concat(callargs_conversion, ", "),
CALLARGSCPPTOC = table.concat(callargs_conversion_back, ", "),
2019-02-27 12:49:28 +03:00
CALLARGS = table.concat(callargs, ", "),
POSTRET = lines(func.ret_postfix),
2019-03-10 09:40:43 +03:00
POSTRETCPPTOC = lines(func.ret_postfix_cpp2c),
PRERETCTOC = preret_c2c,
POSTRETCTOC = lines(postret_c2c),
CLASSNAME = classname,
CONST = func.const and " const" or "",
2019-02-27 12:49:28 +03:00
}
end
local function apply_template(func, temp)
func.codetemp = func.codetemp or codetemp(func)
return (temp:gsub("$(%u+)", func.codetemp))
end
2019-03-10 09:40:43 +03:00
function codegen.apply_functemp(func, temp)
return remove_emptylines(apply_template(func, temp))
end
function codegen.gen_funcptr(funcptr)
return apply_template(funcptr, "typedef $RET (*$FUNCNAME)($ARGS);")
end
function codegen.gen_cfuncptr(funcptr)
return apply_template(funcptr, "typedef $CRET (*$CFUNCNAME)($CARGS);")
end
local function doxygen_funcret(r, func, prefix)
if not func or func.ret.fulltype == "void" or func.ret.comment == nil then
return
end
r[#r+1] = prefix
if type(func.ret.comment) == "string" then
r[#r+1] = string.format("%s @returns %s", prefix, func.ret.comment)
else
r[#r+1] = string.format("%s @returns %s", prefix, func.ret.comment[1])
for i = 2,#func.ret.comment do
r[#r+1] = string.format("%s %s", prefix, func.ret.comment[i])
end
end
return r
end
local function doxygen_func(r, func, prefix)
if not func or not func.args or #func.args == 0 then
return
end
r[#r+1] = prefix
for _, arg in ipairs(func.args) do
local inout
if arg.out then
inout = "out"
elseif arg.inout then
inout = "inout"
else
inout = "in"
end
local comment = string.format("%s @param[%s] %s", prefix, inout, arg.name)
if arg.comment then
if type(arg.comment) == "string" then
r[#r+1] = comment .. " " .. arg.comment
else
r[#r+1] = comment .. " " .. arg.comment[1]
for i = 2,#arg.comment do
r[#r+1] = string.format("%s %s", prefix, arg.comment[i])
end
end
else
r[#r+1] = comment
end
end
doxygen_funcret(r, func, prefix)
return r
end
function codegen.doxygen_type(doxygen, func, cname)
if doxygen == nil then
return
end
local result = {}
for _, line in ipairs(doxygen) do
result[#result+1] = "/// " .. line
end
doxygen_func(result, func, "///")
if cname then
result[#result+1] = "///"
if type(cname) == "string" then
result[#result+1] = string.format("/// @attention C99 equivalent is `%s`.", cname)
else
local names = {}
for _, v in ipairs(cname) do
names[#names+1] = "`" .. v .. "`"
end
result[#result+1] = string.format("/// @attention C99 equivalent are %s.", table.concat(names, ","))
end
end
result[#result+1] = "///"
return table.concat(result, "\n")
end
function codegen.doxygen_ctype(doxygen, func)
if doxygen == nil then
return
end
local result = {
"/**",
}
for _, line in ipairs(doxygen) do
result[#result+1] = " * " .. line
end
doxygen_func(result, func, " *")
result[#result+1] = " *"
result[#result+1] = " */"
return table.concat(result, "\n")
end
local enum_temp = [[
struct $NAME
2019-02-27 12:49:28 +03:00
{
2019-03-10 09:40:43 +03:00
$COMMENT
enum Enum
{
$ITEMS
Count
};
};
2019-02-27 12:49:28 +03:00
]]
2019-03-10 09:40:43 +03:00
function codegen.gen_enum_define(enum)
assert(type(enum.enum) == "table", "Not an enum")
local items = {}
for _, item in ipairs(enum.enum) do
local text
if not item.comment then
text = item.name .. ","
else
text = string.format("%s,%s //!< %s",
item.name, namealign(item.name), item.comment)
end
items[#items+1] = text
end
local comment = ""
if enum.comment then
comment = "/// " .. enum.comment
end
local temp = {
NAME = enum.name,
COMMENT = comment,
ITEMS = table.concat(items, "\n\t\t"),
}
return (enum_temp:gsub("$(%u+)", temp))
end
local cenum_temp = [[
typedef enum $NAME
2019-02-27 12:49:28 +03:00
{
2019-03-10 09:40:43 +03:00
$ITEMS
$COUNT
} $NAME_t;
2019-02-27 12:49:28 +03:00
]]
2019-03-10 09:40:43 +03:00
function codegen.gen_enum_cdefine(enum)
assert(type(enum.enum) == "table", "Not an enum")
local cname = enum.cname:match "(.-)_t$"
local uname = cname:upper()
local items = {}
for index , item in ipairs(enum.enum) do
local comment = item.comment or ""
local ename = item.cname
if not ename then
if enum.underscore then
ename = camelcase_to_underscorecase(item.name)
else
ename = item.name
end
ename = ename:upper()
end
local name = uname .. "_" .. ename
items[#items+1] = string.format("%s,%s /** (%2d) %s%s */",
name,
namealign(name, 40),
index - 1,
comment,
namealign(comment, 30))
end
2019-02-27 12:49:28 +03:00
2019-03-10 09:40:43 +03:00
local temp = {
NAME = cname,
COUNT = uname .. "_COUNT",
ITEMS = table.concat(items, "\n\t"),
}
return (cenum_temp:gsub("$(%u+)", temp))
end
local function text_with_comments(items, item, cstyle, is_classmember)
local name = item.name
if item.array then
if cstyle then
name = name .. (item.carray or item.array)
else
name = name .. item.array
end
end
local typename
if cstyle then
typename = item.ctype
2019-02-27 12:49:28 +03:00
else
2019-03-10 09:40:43 +03:00
typename = item.fulltype
end
if is_classmember then
name = "m_" .. name
2019-02-27 12:49:28 +03:00
end
2019-03-10 09:40:43 +03:00
local text = string.format("%s%s %s;", typename, namealign(typename), name)
if item.comment then
if type(item.comment) == "table" then
table.insert(items, "")
if cstyle then
table.insert(items, "/**")
for _, c in ipairs(item.comment) do
table.insert(items, " * " .. c)
end
table.insert(items, " */")
else
for _, c in ipairs(item.comment) do
table.insert(items, "/// " .. c)
end
end
else
text = string.format(
cstyle and "%s %s/** %s%s */" or "%s %s//!< %s",
text, namealign(text, 40), item.comment, namealign(item.comment, 40))
end
end
items[#items+1] = text
2019-02-27 12:49:28 +03:00
end
2019-03-10 09:40:43 +03:00
local struct_temp = [[
struct $NAME
{
$METHODS
$SUBSTRUCTS
$ITEMS
};
2019-02-27 12:49:28 +03:00
]]
2019-03-10 09:40:43 +03:00
function codegen.gen_struct_define(struct, methods)
assert(type(struct.struct) == "table", "Not a struct")
local items = {}
for _, item in ipairs(struct.struct) do
text_with_comments(items, item, false, methods ~= nil)
end
local ctor = {}
if struct.ctor then
ctor[1] = struct.name .. "();"
ctor[2] = ""
end
if methods then
for _, m in ipairs(methods) do
if m:sub(-1) ~= "\n" then
m = m .. "\n"
end
for line in m:gmatch "(.-)\n" do
ctor[#ctor+1] = line
end
ctor[#ctor+1] = ""
end
end
local subs = {}
if struct.substruct then
for _, v in ipairs(struct.substruct) do
local s = codegen.gen_struct_define(v)
s = s:gsub("\n", "\n\t")
subs[#subs+1] = s
end
end
local temp = {
NAME = struct.name,
SUBSTRUCTS = lines(subs),
ITEMS = table.concat(items, "\n\t"),
METHODS = lines(ctor),
}
return remove_emptylines(struct_temp:gsub("$(%u+)", temp))
2019-02-27 12:49:28 +03:00
end
2019-03-10 09:40:43 +03:00
local cstruct_temp = [[
typedef struct $NAME_s
{
$ITEMS
} $NAME_t;
]]
function codegen.gen_struct_cdefine(struct)
assert(type(struct.struct) == "table", "Not a struct")
local cname = struct.cname:match "(.-)_t$"
local items = {}
for _, item in ipairs(struct.struct) do
text_with_comments(items, item, true)
end
local temp = {
NAME = cname,
ITEMS = table.concat(items, "\n\t"),
}
return (cstruct_temp:gsub("$(%u+)", temp))
2019-02-27 12:49:28 +03:00
end
2019-03-10 09:40:43 +03:00
local chandle_temp = [[
typedef struct $NAME_s { uint16_t idx; } $NAME_t;
]]
function codegen.gen_chandle(handle)
assert(handle.handle, "Not a handle")
return (chandle_temp:gsub("$(%u+)", { NAME = handle.cname:match "(.-)_t$" }))
end
local handle_temp = [[
struct $NAME { uint16_t idx; };
inline bool isValid($NAME _handle) { return bgfx::kInvalidHandle != _handle.idx; }
]]
function codegen.gen_handle(handle)
assert(handle.handle, "Not a handle")
return (handle_temp:gsub("$(%u+)", { NAME = handle.name }))
2019-02-27 12:49:28 +03:00
end
return codegen