PageRenderTime 42ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/tolua++-1.0.93/src/bin/lua/function.lua

https://bitbucket.org/dbindel/axfem
Lua | 577 lines | 456 code | 62 blank | 59 comment | 81 complexity | 636b9cd109cef7d39c0bdb00745bc513 MD5 | raw file
Possible License(s): LGPL-2.1
  1. -- tolua: function class
  2. -- Written by Waldemar Celes
  3. -- TeCGraf/PUC-Rio
  4. -- Jul 1998
  5. -- $Id: $
  6. -- This code is free software; you can redistribute it and/or modify it.
  7. -- The software provided hereunder is on an "as is" basis, and
  8. -- the author has no obligation to provide maintenance, support, updates,
  9. -- enhancements, or modifications.
  10. -- Function class
  11. -- Represents a function or a class method.
  12. -- The following fields are stored:
  13. -- mod = type modifiers
  14. -- type = type
  15. -- ptr = "*" or "&", if representing a pointer or a reference
  16. -- name = name
  17. -- lname = lua name
  18. -- args = list of argument declarations
  19. -- const = if it is a method receiving a const "this".
  20. classFunction = {
  21. mod = '',
  22. type = '',
  23. ptr = '',
  24. name = '',
  25. args = {n=0},
  26. const = '',
  27. }
  28. classFunction.__index = classFunction
  29. setmetatable(classFunction,classFeature)
  30. -- declare tags
  31. function classFunction:decltype ()
  32. self.type = typevar(self.type)
  33. if strfind(self.mod,'const') then
  34. self.type = 'const '..self.type
  35. self.mod = gsub(self.mod,'const','')
  36. end
  37. local i=1
  38. while self.args[i] do
  39. self.args[i]:decltype()
  40. i = i+1
  41. end
  42. end
  43. -- Write binding function
  44. -- Outputs C/C++ binding function.
  45. function classFunction:supcode (local_constructor)
  46. local overload = strsub(self.cname,-2,-1) - 1 -- indicate overloaded func
  47. local nret = 0 -- number of returned values
  48. local class = self:inclass()
  49. local _,_,static = strfind(self.mod,'^%s*(static)')
  50. if class then
  51. if self.name == 'new' and self.parent.flags.pure_virtual then
  52. -- no constructor for classes with pure virtual methods
  53. return
  54. end
  55. if local_constructor then
  56. output("/* method: new_local of class ",class," */")
  57. else
  58. output("/* method:",self.name," of class ",class," */")
  59. end
  60. else
  61. output("/* function:",self.name," */")
  62. end
  63. if local_constructor then
  64. output("#ifndef TOLUA_DISABLE_"..self.cname.."_local")
  65. output("\nstatic int",self.cname.."_local","(lua_State* tolua_S)")
  66. else
  67. output("#ifndef TOLUA_DISABLE_"..self.cname)
  68. output("\nstatic int",self.cname,"(lua_State* tolua_S)")
  69. end
  70. output("{")
  71. -- check types
  72. if overload < 0 then
  73. output('#ifndef TOLUA_RELEASE\n')
  74. end
  75. output(' tolua_Error tolua_err;')
  76. output(' if (\n')
  77. -- check self
  78. local narg
  79. if class then narg=2 else narg=1 end
  80. if class then
  81. local func = get_is_function(self.parent.type)
  82. local type = self.parent.type
  83. if self.name=='new' or static~=nil then
  84. func = 'tolua_isusertable'
  85. type = self.parent.type
  86. end
  87. if self.const ~= '' then
  88. type = "const "..type
  89. end
  90. output(' !'..func..'(tolua_S,1,"'..type..'",0,&tolua_err) ||\n')
  91. end
  92. -- check args
  93. if self.args[1].type ~= 'void' then
  94. local i=1
  95. while self.args[i] do
  96. local btype = isbasic(self.args[i].type)
  97. if btype ~= 'value' and btype ~= 'state' then
  98. output(' '..self.args[i]:outchecktype(narg)..' ||\n')
  99. end
  100. if btype ~= 'state' then
  101. narg = narg+1
  102. end
  103. i = i+1
  104. end
  105. end
  106. -- check end of list
  107. output(' !tolua_isnoobj(tolua_S,'..narg..',&tolua_err)\n )')
  108. output(' goto tolua_lerror;')
  109. output(' else\n')
  110. if overload < 0 then
  111. output('#endif\n')
  112. end
  113. output(' {')
  114. -- declare self, if the case
  115. local narg
  116. if class then narg=2 else narg=1 end
  117. if class and self.name~='new' and static==nil then
  118. output(' ',self.const,self.parent.type,'*','self = ')
  119. output('(',self.const,self.parent.type,'*) ')
  120. local to_func = get_to_function(self.parent.type)
  121. output(to_func,'(tolua_S,1,0);')
  122. elseif static then
  123. _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
  124. end
  125. -- declare parameters
  126. if self.args[1].type ~= 'void' then
  127. local i=1
  128. while self.args[i] do
  129. self.args[i]:declare(narg)
  130. if isbasic(self.args[i].type) ~= "state" then
  131. narg = narg+1
  132. end
  133. i = i+1
  134. end
  135. end
  136. -- check self
  137. if class and self.name~='new' and static==nil then
  138. output('#ifndef TOLUA_RELEASE\n')
  139. output(' if (!self) tolua_error(tolua_S,"'..output_error_hook("invalid \'self\' in function \'%s\'", self.name)..'", NULL);');
  140. output('#endif\n')
  141. end
  142. -- get array element values
  143. if class then narg=2 else narg=1 end
  144. if self.args[1].type ~= 'void' then
  145. local i=1
  146. while self.args[i] do
  147. self.args[i]:getarray(narg)
  148. narg = narg+1
  149. i = i+1
  150. end
  151. end
  152. pre_call_hook(self)
  153. local out = string.find(self.mod, "tolua_outside")
  154. -- call function
  155. if class and self.name=='delete' then
  156. output(' Mtolua_delete(self);')
  157. elseif class and self.name == 'operator&[]' then
  158. if flags['1'] then -- for compatibility with tolua5 ?
  159. output(' self->operator[](',self.args[1].name,'-1) = ',self.args[2].name,';')
  160. else
  161. output(' self->operator[](',self.args[1].name,') = ',self.args[2].name,';')
  162. end
  163. else
  164. output(' {')
  165. if self.type ~= '' and self.type ~= 'void' then
  166. output(' ',self.mod,self.type,self.ptr,'tolua_ret = ')
  167. output('(',self.mod,self.type,self.ptr,') ')
  168. else
  169. output(' ')
  170. end
  171. if class and self.name=='new' then
  172. output('Mtolua_new((',self.type,')(')
  173. elseif class and static then
  174. if out then
  175. output(self.name,'(')
  176. else
  177. output(class..'::'..self.name,'(')
  178. end
  179. elseif class then
  180. if out then
  181. output(self.name,'(')
  182. else
  183. if self.cast_operator then
  184. --output('static_cast<',self.mod,self.type,self.ptr,' >(*self')
  185. output('self->operator ',self.mod,self.type,'(')
  186. else
  187. output('self->'..self.name,'(')
  188. end
  189. end
  190. else
  191. output(self.name,'(')
  192. end
  193. if out and not static then
  194. output('self')
  195. if self.args[1] and self.args[1].name ~= '' then
  196. output(',')
  197. end
  198. end
  199. -- write parameters
  200. local i=1
  201. while self.args[i] do
  202. self.args[i]:passpar()
  203. i = i+1
  204. if self.args[i] then
  205. output(',')
  206. end
  207. end
  208. if class and self.name == 'operator[]' and flags['1'] then
  209. output('-1);')
  210. else
  211. if class and self.name=='new' then
  212. output('));') -- close Mtolua_new(
  213. else
  214. output(');')
  215. end
  216. end
  217. -- return values
  218. if self.type ~= '' and self.type ~= 'void' then
  219. nret = nret + 1
  220. local t,ct = isbasic(self.type)
  221. if t and self.name ~= "new" then
  222. if self.cast_operator and _basic_raw_push[t] then
  223. output(' ',_basic_raw_push[t],'(tolua_S,(',ct,')tolua_ret);')
  224. else
  225. output(' tolua_push'..t..'(tolua_S,(',ct,')tolua_ret);')
  226. end
  227. else
  228. t = self.type
  229. new_t = string.gsub(t, "const%s+", "")
  230. local owned = false
  231. if string.find(self.mod, "tolua_owned") then
  232. owned = true
  233. end
  234. local push_func = get_push_function(t)
  235. if self.ptr == '' then
  236. output(' {')
  237. output('#ifdef __cplusplus\n')
  238. output(' void* tolua_obj = Mtolua_new((',new_t,')(tolua_ret));')
  239. output(' ',push_func,'(tolua_S,tolua_obj,"',t,'");')
  240. output(' tolua_register_gc(tolua_S,lua_gettop(tolua_S));')
  241. output('#else\n')
  242. output(' void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(',t,'));')
  243. output(' ',push_func,'(tolua_S,tolua_obj,"',t,'");')
  244. output(' tolua_register_gc(tolua_S,lua_gettop(tolua_S));')
  245. output('#endif\n')
  246. output(' }')
  247. elseif self.ptr == '&' then
  248. output(' ',push_func,'(tolua_S,(void*)&tolua_ret,"',t,'");')
  249. else
  250. output(' ',push_func,'(tolua_S,(void*)tolua_ret,"',t,'");')
  251. if owned or local_constructor then
  252. output(' tolua_register_gc(tolua_S,lua_gettop(tolua_S));')
  253. end
  254. end
  255. end
  256. end
  257. local i=1
  258. while self.args[i] do
  259. nret = nret + self.args[i]:retvalue()
  260. i = i+1
  261. end
  262. output(' }')
  263. -- set array element values
  264. if class then narg=2 else narg=1 end
  265. if self.args[1].type ~= 'void' then
  266. local i=1
  267. while self.args[i] do
  268. self.args[i]:setarray(narg)
  269. narg = narg+1
  270. i = i+1
  271. end
  272. end
  273. -- free dynamically allocated array
  274. if self.args[1].type ~= 'void' then
  275. local i=1
  276. while self.args[i] do
  277. self.args[i]:freearray()
  278. i = i+1
  279. end
  280. end
  281. end
  282. post_call_hook(self)
  283. output(' }')
  284. output(' return '..nret..';')
  285. -- call overloaded function or generate error
  286. if overload < 0 then
  287. output('#ifndef TOLUA_RELEASE\n')
  288. output('tolua_lerror:\n')
  289. output(' tolua_error(tolua_S,"'..output_error_hook("#ferror in function \'%s\'.", self.lname)..'",&tolua_err);')
  290. output(' return 0;')
  291. output('#endif\n')
  292. else
  293. local _local = ""
  294. if local_constructor then
  295. _local = "_local"
  296. end
  297. output('tolua_lerror:\n')
  298. output(' return '..strsub(self.cname,1,-3)..format("%02d",overload).._local..'(tolua_S);')
  299. end
  300. output('}')
  301. output('#endif //#ifndef TOLUA_DISABLE\n')
  302. output('\n')
  303. -- recursive call to write local constructor
  304. if class and self.name=='new' and not local_constructor then
  305. self:supcode(1)
  306. end
  307. end
  308. -- register function
  309. function classFunction:register (pre)
  310. if not self:check_public_access() then
  311. return
  312. end
  313. if self.name == 'new' and self.parent.flags.pure_virtual then
  314. -- no constructor for classes with pure virtual methods
  315. return
  316. end
  317. output(pre..'tolua_function(tolua_S,"'..self.lname..'",'..self.cname..');')
  318. if self.name == 'new' then
  319. output(pre..'tolua_function(tolua_S,"new_local",'..self.cname..'_local);')
  320. output(pre..'tolua_function(tolua_S,".call",'..self.cname..'_local);')
  321. --output(' tolua_set_call_event(tolua_S,'..self.cname..'_local, "'..self.parent.type..'");')
  322. end
  323. end
  324. -- Print method
  325. function classFunction:print (ident,close)
  326. print(ident.."Function{")
  327. print(ident.." mod = '"..self.mod.."',")
  328. print(ident.." type = '"..self.type.."',")
  329. print(ident.." ptr = '"..self.ptr.."',")
  330. print(ident.." name = '"..self.name.."',")
  331. print(ident.." lname = '"..self.lname.."',")
  332. print(ident.." const = '"..self.const.."',")
  333. print(ident.." cname = '"..self.cname.."',")
  334. print(ident.." lname = '"..self.lname.."',")
  335. print(ident.." args = {")
  336. local i=1
  337. while self.args[i] do
  338. self.args[i]:print(ident.." ",",")
  339. i = i+1
  340. end
  341. print(ident.." }")
  342. print(ident.."}"..close)
  343. end
  344. -- check if it returns an object by value
  345. function classFunction:requirecollection (t)
  346. local r = false
  347. if self.type ~= '' and not isbasic(self.type) and self.ptr=='' then
  348. local type = gsub(self.type,"%s*const%s+","")
  349. t[type] = "tolua_collect_" .. clean_template(type)
  350. r = true
  351. end
  352. local i=1
  353. while self.args[i] do
  354. r = self.args[i]:requirecollection(t) or r
  355. i = i+1
  356. end
  357. return r
  358. end
  359. -- determine lua function name overload
  360. function classFunction:overload ()
  361. return self.parent:overload(self.lname)
  362. end
  363. function param_object(par) -- returns true if the parameter has an object as its default value
  364. if not string.find(par, '=') then return false end -- it has no default value
  365. local _,_,def = string.find(par, "=(.*)$")
  366. if string.find(par, "|") then -- a list of flags
  367. return true
  368. end
  369. if string.find(par, "%*") then -- it's a pointer with a default value
  370. if string.find(par, '=%s*new') or string.find(par, "%(") then -- it's a pointer with an instance as default parameter.. is that valid?
  371. return true
  372. end
  373. return false -- default value is 'NULL' or something
  374. end
  375. if string.find(par, "[%(&]") then
  376. return true
  377. end -- default value is a constructor call (most likely for a const reference)
  378. --if string.find(par, "&") then
  379. -- if string.find(def, ":") or string.find(def, "^%s*new%s+") then
  380. -- -- it's a reference with default to something like Class::member, or 'new Class'
  381. -- return true
  382. -- end
  383. --end
  384. return false -- ?
  385. end
  386. function strip_last_arg(all_args, last_arg) -- strips the default value from the last argument
  387. local _,_,s_arg = string.find(last_arg, "^([^=]+)")
  388. last_arg = string.gsub(last_arg, "([%%%(%)])", "%%%1");
  389. all_args = string.gsub(all_args, "%s*,%s*"..last_arg.."%s*%)%s*$", ")")
  390. return all_args, s_arg
  391. end
  392. -- Internal constructor
  393. function _Function (t)
  394. setmetatable(t,classFunction)
  395. if t.const ~= 'const' and t.const ~= '' then
  396. error("#invalid 'const' specification")
  397. end
  398. append(t)
  399. if t:inclass() then
  400. --print ('t.name is '..t.name..', parent.name is '..t.parent.name)
  401. if string.gsub(t.name, "%b<>", "") == string.gsub(t.parent.original_name or t.parent.name, "%b<>", "") then
  402. t.name = 'new'
  403. t.lname = 'new'
  404. t.parent._new = true
  405. t.type = t.parent.name
  406. t.ptr = '*'
  407. elseif string.gsub(t.name, "%b<>", "") == '~'..string.gsub(t.parent.original_name or t.parent.name, "%b<>", "") then
  408. t.name = 'delete'
  409. t.lname = 'delete'
  410. t.parent._delete = true
  411. end
  412. end
  413. t.cname = t:cfuncname("tolua")..t:overload(t)
  414. return t
  415. end
  416. -- Constructor
  417. -- Expects three strings: one representing the function declaration,
  418. -- another representing the argument list, and the third representing
  419. -- the "const" or empty string.
  420. function Function (d,a,c)
  421. --local t = split(strsub(a,2,-2),',') -- eliminate braces
  422. --local t = split_params(strsub(a,2,-2))
  423. if not flags['W'] and string.find(a, "%.%.%.%s*%)") then
  424. warning("Functions with variable arguments (`...') are not supported. Ignoring "..d..a..c)
  425. return nil
  426. end
  427. local i=1
  428. local l = {n=0}
  429. a = string.gsub(a, "%s*([%(%)])%s*", "%1")
  430. local t,strip,last = strip_pars(strsub(a,2,-2));
  431. if strip then
  432. --local ns = string.sub(strsub(a,1,-2), 1, -(string.len(last)+1))
  433. local ns = join(t, ",", 1, last-1)
  434. ns = "("..string.gsub(ns, "%s*,%s*$", "")..')'
  435. --ns = strip_defaults(ns)
  436. local f = Function(d, ns, c)
  437. for i=1,last do
  438. t[i] = string.gsub(t[i], "=.*$", "")
  439. end
  440. end
  441. while t[i] do
  442. l.n = l.n+1
  443. l[l.n] = Declaration(t[i],'var',true)
  444. i = i+1
  445. end
  446. local f = Declaration(d,'func')
  447. f.args = l
  448. f.const = c
  449. return _Function(f)
  450. end
  451. function join(t, sep, first, last)
  452. first = first or 1
  453. last = last or table.getn(t)
  454. local lsep = ""
  455. local ret = ""
  456. local loop = false
  457. for i = first,last do
  458. ret = ret..lsep..t[i]
  459. lsep = sep
  460. loop = true
  461. end
  462. if not loop then
  463. return ""
  464. end
  465. return ret
  466. end
  467. function strip_pars(s)
  468. local t = split_c_tokens(s, ',')
  469. local strip = false
  470. local last
  471. for i=t.n,1,-1 do
  472. if not strip and param_object(t[i]) then
  473. last = i
  474. strip = true
  475. end
  476. --if strip then
  477. -- t[i] = string.gsub(t[i], "=.*$", "")
  478. --end
  479. end
  480. return t,strip,last
  481. end
  482. function strip_defaults(s)
  483. s = string.gsub(s, "^%(", "")
  484. s = string.gsub(s, "%)$", "")
  485. local t = split_c_tokens(s, ",")
  486. local sep, ret = "",""
  487. for i=1,t.n do
  488. t[i] = string.gsub(t[i], "=.*$", "")
  489. ret = ret..sep..t[i]
  490. sep = ","
  491. end
  492. return "("..ret..")"
  493. end