idl.lua 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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. local last = item.comment
  60. if last then
  61. if type(last) == "string" then
  62. item.comment = { last, comment }
  63. else
  64. table.insert(item.comment, comment)
  65. end
  66. else
  67. item.comment = comment
  68. end
  69. end
  70. local function enumdef(what)
  71. local function deffunc (_, typename)
  72. local t = new_type(typename)
  73. t[what] = {}
  74. local function enum_attrib(obj, attribs)
  75. copy_attribs(t, attribs)
  76. return obj
  77. end
  78. local function new_enum_item(_, itemname)
  79. local item = { name = itemname }
  80. t[what][#t[what] + 1] = item
  81. local function add_attrib_or_comment(obj , attribs)
  82. if type(attribs) == "string" then
  83. add_comment(item, attribs)
  84. elseif attribs then
  85. copy_attribs(item, attribs)
  86. end
  87. return obj
  88. end
  89. return setmetatable({}, { __index = new_enum_item, __call = add_attrib_or_comment })
  90. end
  91. return setmetatable({}, { __index = new_enum_item , __call = enum_attrib })
  92. end
  93. return setmetatable({} , { __index = deffunc , __call = deffunc })
  94. end
  95. idl.enum = enumdef "enum"
  96. idl.flag = enumdef "flag"
  97. local function structdef(_, typename)
  98. local t = new_type(typename)
  99. t.struct = {}
  100. local function struct_attrib(obj, attribs)
  101. copy_attribs(t, attribs)
  102. return obj
  103. end
  104. local function new_struct_item(_, itemname)
  105. local item = { name = itemname }
  106. t.struct[#t.struct + 1] = item
  107. local function item_attrib(obj, attribs)
  108. if type(attribs) == "string" then
  109. add_comment(item, attribs)
  110. else
  111. copy_attribs(item, attribs)
  112. end
  113. return obj
  114. end
  115. return function (itemtype)
  116. item.fulltype = itemtype
  117. return setmetatable({}, { __index = new_struct_item, __call = item_attrib })
  118. end
  119. end
  120. return setmetatable({}, { __index = new_struct_item , __call = struct_attrib })
  121. end
  122. idl.struct = setmetatable({}, { __index = structdef , __call = structdef })
  123. local function handledef(_, typename)
  124. local t = new_type(typename)
  125. t.handle = true
  126. return function (attribs)
  127. copy_attribs(t, attribs)
  128. return obj
  129. end
  130. end
  131. idl.handle = setmetatable({} , { __index = handledef, __call = handledef })
  132. local all_funcs = {}
  133. local function duplicate_arg_name(_, name)
  134. error ("Duplicate arg name " .. name)
  135. end
  136. local function attribs_setter(args, arg, args_desc)
  137. local attribs_setter
  138. local function arg_attrib_or_comment(_, attrib_or_comment )
  139. if type(attrib_or_comment) == "string" then
  140. add_comment(arg, attrib_or_comment)
  141. else
  142. copy_attribs(arg, attrib_or_comment)
  143. end
  144. return attribs_setter
  145. end
  146. -- next field (__index) or attrib/comment (__call)
  147. attribs_setter = setmetatable( {} , {
  148. __index = function(_, name)
  149. return args_desc(args, name)
  150. end
  151. , __call = arg_attrib_or_comment } )
  152. return attribs_setter
  153. end
  154. local function func(sets)
  155. return function (_, funcname)
  156. local f = { name = funcname , args = {} }
  157. if #comments > 0 then
  158. f.comments = comments
  159. comments = {}
  160. end
  161. sets[#sets+1] = f
  162. local args
  163. local function args_desc(_, args_name)
  164. args[args_name] = duplicate_arg_name
  165. return function (fulltype)
  166. local arg = {
  167. name = "_" .. args_name,
  168. fulltype = fulltype,
  169. }
  170. f.args[#f.args+1] = arg
  171. return attribs_setter(args, arg, args_desc)
  172. end
  173. end
  174. args = setmetatable({}, { __index = args_desc })
  175. local function rettype(value)
  176. assert(type(value) == "string", "Need return type")
  177. local ret = { fulltype = value }
  178. f.ret = ret
  179. return attribs_setter(args, ret, args_desc)
  180. end
  181. local function funcdef(value)
  182. if type(value) == "table" then
  183. copy_attribs(f, value)
  184. return rettype
  185. end
  186. return rettype(value)
  187. end
  188. return classdef(f, funcdef)
  189. end
  190. end
  191. idl.funcptr = setmetatable({}, { __index = func(all_types) })
  192. idl.func = setmetatable({}, { __index = func(all_funcs) })
  193. idl.funcs = all_funcs
  194. function idl.version(v)
  195. rawset(idl, "_version", v)
  196. end
  197. idl.vararg = "vararg"
  198. idl.out = "out"
  199. idl.inout = "inout"
  200. idl.const = "const"
  201. idl.ctor = "ctor"
  202. idl.cfunc = "cfunc"
  203. idl.underscore = "underscore"
  204. idl.conly = "conly"
  205. idl.cpponly = "cpponly"
  206. idl.shortname = "shortname"
  207. idl.NULL = "NULL"
  208. idl.UINT16_MAX = "UINT16_MAX"
  209. idl.INT32_MAX = "INT32_MAX"
  210. idl.UINT32_MAX = "UINT32_MAX"
  211. idl.UINT8_MAX = "UINT8_MAX"
  212. return setmetatable(idl , { __index = function (_, keyword)
  213. error (tostring(keyword) .. " is invalid")
  214. end})