idl.lua 5.5 KB

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