idl.lua 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. -- Copyright 2019 云风 https://github.com/cloudwu . All rights reserved.
  2. -- License (the same with bgfx) : https://github.com/bkaradzic/bgfx/blob/master/LICENSE
  3. local idl = {}
  4. local comments = {}
  5. function idl.comment(c)
  6. comments[#comments+1] = c
  7. end
  8. local all_types = {}
  9. local function copy_attribs(to, from)
  10. if type(from) == "table" then
  11. for k, v in pairs(from) do
  12. if type(k) == "number" then
  13. to[v] = true
  14. end
  15. to[k] = v
  16. end
  17. else
  18. to.value = from
  19. end
  20. end
  21. local function classdef(item, def)
  22. local function class(_, methodname)
  23. item.class = item.name
  24. item.name = methodname
  25. return def
  26. end
  27. return setmetatable({} , { __index = class, __call = function(_, value) return def(value) end })
  28. end
  29. local function new_type(typename)
  30. local t = { name = typename }
  31. if #comments > 0 then
  32. t.comments = comments
  33. comments = {}
  34. end
  35. all_types[#all_types+1] = t
  36. return t
  37. end
  38. local function typedef(_, typename)
  39. local t = new_type(typename)
  40. local function type_attrib(attrib)
  41. copy_attribs(t, attrib)
  42. end
  43. return function(cname)
  44. local typ = type(cname)
  45. if typ == "table" then
  46. type_attrib(cname)
  47. return
  48. end
  49. assert(typ == "string" , "type should be a string")
  50. t.cname = cname
  51. return type_attrib
  52. end
  53. end
  54. idl.typedef = setmetatable({} , { __index = typedef, __call = typedef })
  55. idl.types = all_types
  56. local function add_comment(item, comment)
  57. -- strip space
  58. comment = comment:match "(.-)%s*$"
  59. if item.comment then
  60. table.insert(item.comment, comment)
  61. else
  62. item.comment = { comment }
  63. end
  64. end
  65. local function enumdef(what)
  66. local function deffunc (_, typename)
  67. local t = new_type(typename)
  68. t[what] = {}
  69. local function enum_attrib(obj, attribs)
  70. copy_attribs(t, attribs)
  71. return obj
  72. end
  73. local function new_enum_item(_, itemname)
  74. local item = { name = itemname }
  75. t[what][#t[what] + 1] = item
  76. local function add_attrib_or_comment(obj , attribs)
  77. if type(attribs) == "string" then
  78. add_comment(item, attribs)
  79. elseif attribs then
  80. copy_attribs(item, attribs)
  81. end
  82. return obj
  83. end
  84. return setmetatable({}, { __index = new_enum_item, __call = add_attrib_or_comment })
  85. end
  86. return setmetatable({}, { __index = new_enum_item , __call = enum_attrib })
  87. end
  88. return setmetatable({} , { __index = deffunc , __call = deffunc })
  89. end
  90. idl.enum = enumdef "enum"
  91. idl.flag = enumdef "flag"
  92. local function structdef(_, typename)
  93. local t = new_type(typename)
  94. t.struct = {}
  95. local function struct_attrib(obj, attribs)
  96. copy_attribs(t, attribs)
  97. return obj
  98. end
  99. local function new_struct_item(_, itemname)
  100. local item = { name = itemname }
  101. t.struct[#t.struct + 1] = item
  102. local function item_attrib(obj, attribs)
  103. if type(attribs) == "string" then
  104. add_comment(item, attribs)
  105. else
  106. copy_attribs(item, attribs)
  107. end
  108. return obj
  109. end
  110. return function (itemtype)
  111. item.fulltype = itemtype
  112. return setmetatable({}, { __index = new_struct_item, __call = item_attrib })
  113. end
  114. end
  115. return setmetatable({}, { __index = new_struct_item , __call = struct_attrib })
  116. end
  117. idl.struct = setmetatable({}, { __index = structdef , __call = structdef })
  118. local function handledef(_, typename)
  119. local t = new_type(typename)
  120. t.handle = true
  121. return function (attribs)
  122. copy_attribs(t, attribs)
  123. return obj
  124. end
  125. end
  126. idl.handle = setmetatable({} , { __index = handledef, __call = handledef })
  127. local all_funcs = {}
  128. local function duplicate_arg_name(_, name)
  129. error ("Duplicate arg name " .. name)
  130. end
  131. local function attribs_setter(args, arg, args_desc)
  132. local attribs_setter
  133. local function arg_attrib_or_comment(_, attrib_or_comment )
  134. if type(attrib_or_comment) == "string" then
  135. add_comment(arg, attrib_or_comment)
  136. else
  137. copy_attribs(arg, attrib_or_comment)
  138. end
  139. return attribs_setter
  140. end
  141. -- next field (__index) or attrib/comment (__call)
  142. attribs_setter = setmetatable( {} , {
  143. __index = function(_, name)
  144. return args_desc(args, name)
  145. end
  146. , __call = arg_attrib_or_comment } )
  147. return attribs_setter
  148. end
  149. local function func(sets)
  150. return function (_, funcname)
  151. local f = { name = funcname , args = {} }
  152. if #comments > 0 then
  153. f.comments = comments
  154. comments = {}
  155. end
  156. sets[#sets+1] = f
  157. local args
  158. local function args_desc(_, args_name)
  159. args[args_name] = duplicate_arg_name
  160. return function (fulltype)
  161. local arg = {
  162. name = "_" .. args_name,
  163. fulltype = fulltype,
  164. }
  165. f.args[#f.args+1] = arg
  166. return attribs_setter(args, arg, args_desc)
  167. end
  168. end
  169. args = setmetatable({}, { __index = args_desc })
  170. local function rettype(value)
  171. assert(type(value) == "string", "Need return type")
  172. local ret = { fulltype = value }
  173. f.ret = ret
  174. return attribs_setter(args, ret, args_desc)
  175. end
  176. local function funcdef(value)
  177. if type(value) == "table" then
  178. copy_attribs(f, value)
  179. return rettype
  180. end
  181. return rettype(value)
  182. end
  183. return classdef(f, funcdef)
  184. end
  185. end
  186. idl.funcptr = setmetatable({}, { __index = func(all_types) })
  187. idl.func = setmetatable({}, { __index = func(all_funcs) })
  188. idl.funcs = all_funcs
  189. function idl.version(v)
  190. rawset(idl, "_version", v)
  191. end
  192. idl.vararg = "vararg"
  193. idl.out = "out"
  194. idl.inout = "inout"
  195. idl.const = "const"
  196. idl.ctor = "ctor"
  197. idl.cfunc = "cfunc"
  198. idl.underscore = "underscore"
  199. idl.conly = "conly"
  200. idl.cpponly = "cpponly"
  201. idl.cppinline = "cppinline"
  202. idl.shortname = "shortname"
  203. idl.NULL = "NULL"
  204. idl.UINT16_MAX = "UINT16_MAX"
  205. idl.INT32_MAX = "INT32_MAX"
  206. idl.UINT32_MAX = "UINT32_MAX"
  207. idl.UINT8_MAX = "UINT8_MAX"
  208. return setmetatable(idl , { __index = function (_, keyword)
  209. error (tostring(keyword) .. " is invalid")
  210. end})