Added support for properties/public variables.
[lqt/mk.git] / old_bindings / script / generate_bind.lua
blob1d40914a42886b0495b04a4738fc32a40a26affc
1 #!/usr/bin/lua
2 --[[
4 Copyright (c) 2007 Mauro Iazzi
6 Permission is hereby granted, free of charge, to any person
7 obtaining a copy of this software and associated documentation
8 files (the "Software"), to deal in the Software without
9 restriction, including without limitation the rights to use,
10 copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the
12 Software is furnished to do so, subject to the following
13 conditions:
15 The above copyright notice and this permission notice shall be
16 included in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 OTHER DEALINGS IN THE SOFTWARE.
27 --]]
30 require 'lxp'
31 require 'lxp.lom'
33 filename = 'main.xml'
34 my_typename = 'QObject'
36 hpp_text = ''
37 hpp_public = ''
38 hpp_private = ''
39 hpp_protected = ''
40 cpp_text = ''
42 hpp = function(fn) io.write(hpp_text) print() end
43 cpp = function(fn) io.write(cpp_text) print() end
44 wr = function(fn) local f = io.open('bind.hpp', 'w') f:write(hpp_text) f:write'\n' f:close() end
46 xmlf = io.open(filename, 'r')
47 xmls = xmls or xmlf:read('*a')
48 xmlf:close()
49 xmlt = xmlt or lxp.lom.parse(xmls)
50 xmlf, xmls = nil, nil
53 ------------ FIND -------------
54 find = function (t, f)
55 if type(t)~='table' then
56 return nil
57 end;
58 if f(t) then
59 return t
60 end
61 local ret = nil
62 for k,v in pairs(t) do
63 ret = ret or find(v, f)
64 if ret then break end
65 end;
66 return ret;
67 end
69 name_search = function (n)
70 return function(t)
71 return (type(t)=='table') and (type(t.attr)=='table') and (t.attr.name==n)
72 end
73 end
75 id_search = function (i)
76 return function (t)
77 return (type(t)=='table') and (type(t.attr)=='table') and (t.attr.id==i) -- or ((type(i)=='table') and i[t.attr.id])
78 end
79 end
81 tag_search = function (n)
82 return function (t)
83 return (type(t)=='table') and (t.tag==n) -- or ((type(i)==table) and i[t.attr.id])
84 end
85 end
87 find_name = function (n) return find(xmlt, name_search(n)) end
88 find_id = function (n) return find(xmlt, id_search(n)) end
91 ------------ ---- -------------
93 --[[
94 type_name = function (t, el)
95 if el.tag == 'FundamentalType' then
96 return el.attr.name
97 elseif (el.tag == 'Class') or (el.tag == 'Struct') then
98 return el.attr.name
99 elseif el.tag == 'Typedef' then
100 return type_name_by_id(t, el.attr.type)
101 elseif el.tag == 'PointerType' then
102 return type_name_by_id(t, el.attr.type) .. ' *'
103 elseif el.tag == 'ReferenceType' then
104 return type_name_by_id(t, el.attr.type) .. '&'
105 elseif el.tag == 'CvQualifiedType' then
106 return ( (el.attr.volatile=='1') and 'volatile ' or '') .. ( (el.attr.const=='1') and 'const ' or '') .. type_name_by_id(t, el.attr.type)
107 else
108 print (el.attr.id)
109 return '<>'
112 --]]
114 type_name = {}
115 setmetatable(type_name, {
116 __call = function (t, el)
117 print('getting name of', el, el.tag)
118 if t[el] then return t[el] end
119 if el.tag == 'FundamentalType' then
120 t[el] = el.attr.name
121 elseif (el.tag == 'Class') or (el.tag == 'Struct') then
122 t[el] = el.attr.name
123 elseif el.tag == 'Typedef' then
124 t[el] = t(find_id(el.attr.type))
125 elseif el.tag == 'PointerType' then
126 t[el] = t(find_id(el.attr.type)) .. ' *'
127 elseif el.tag == 'ReferenceType' then
128 t[el] = t(find_id(el.attr.type)) .. '&'
129 elseif el.tag == 'CvQualifiedType' then
130 t[el] = ( (el.attr.volatile=='1') and 'volatile ' or '') .. ( (el.attr.const=='1') and 'const ' or '') .. t(find_id(el.attr.type))
131 elseif el.tag == 'Enumeration' then
132 t[el] = ((find_id(el.attr.context).attr.name=='::') and '' or
133 (find_id(el.attr.context).attr.name) .. '::') .. el.attr.name
134 else
135 -- error'SHIT!'
136 -- table.foreach(el, print)
137 -- table.foreach(el.attr, print)
138 -- print (el.attr.id)
139 t[el] = '<>'
141 return rawget(t,el)
147 function get_base_pointer_to(n, i)
148 return '*static_cast<' .. n .. '**>(luaL_checkudata(L, ' .. tostring(i) .. ', "' .. n .. '*"))'
153 type_from_stack = {}
155 local type_from_stack_mt = {
156 ['const char *'] = function(i) return 'lua_tostring(L, ' .. tostring(i) .. ')' end,
157 ['short int'] = function(i) return 'lua_tointeger(L, ' .. tostring(i) .. ')' end,
158 ['unsigned short int'] = function(i) return 'lua_tointeger(L, ' .. tostring(i) .. ')' end,
159 ['int'] = function(i) return 'lua_tointeger(L, ' .. tostring(i) .. ')' end,
160 ['unsigned int'] = function(i) return 'lua_tointeger(L, ' .. tostring(i) .. ')' end,
161 ['long int'] = function(i) return 'lua_tointeger(L, ' .. tostring(i) .. ')' end,
162 ['unsigned long int'] = function(i) return 'lua_tointeger(L, ' .. tostring(i) .. ')' end,
163 ['long long int'] = function(i) return 'lua_tointeger(L, ' .. tostring(i) .. ')' end,
164 ['unsigned long long int'] = function(i) return 'lua_tointeger(L, ' .. tostring(i) .. ')' end,
165 ['float'] = function(i) return 'lua_tonumber(L, ' .. tostring(i) .. ')' end,
166 ['double'] = function(i) return 'lua_tonumber(L, ' .. tostring(i) .. ')' end,
167 ['bool'] = function(i) return '(bool)lua_toboolean(L, ' .. tostring(i) .. ')' end,
168 ['void *'] = function(i) return 'lua_touserdata(L, ' .. tostring(i) .. ')' end,
169 ['void * *'] = function(i) return 'static_cast<void **>(lua_touserdata(L, ' .. tostring(i) .. '))' end,
171 setmetatable(type_from_stack, type_from_stack_mt)
172 type_from_stack_mt.__call = function (t, el, i)
173 local name = type_name(el)
174 -- if t[el] then return t[el] end
175 if type(type_from_stack_mt[name])=='function' then
176 t[el] = type_from_stack_mt[name](i)
177 else
178 if (el.tag=='Class') or (el.tag=='Struct') then
179 t[el] = '*' .. get_base_pointer_to(name, i)
180 elseif (el.tag=='CvQualifiedType') then
181 t[el] = t(find_id(el.attr.type), i)
182 elseif (el.tag=='ReferenceType') then
183 t[el] = t(find_id(el.attr.type), i)
184 elseif (el.tag=='Enumeration') then
185 t[el] = 'static_cast<'..name..'>(luaL_toenum(L, '..tostring(i)..', "'..name..'"))'
186 elseif (el.tag=='PointerType') then
187 t[el] = 'static_cast<'..type_name(el).. '>(&(' .. t(find_id(el.attr.type), i) .. '))'
190 print (el.tag, el, rawget(t,el) or '<>')
191 return rawget(t,el) or '<>'
195 type_on_stack_test = {}
197 local type_on_stack_test_mt = {
198 ['const char *'] = function(i) return '(lua_type(L, ' .. tostring(i) .. ')==LUA_TSTRING)' end,
199 ['short int'] = function(i) return 'lua_isinteger(L, ' .. tostring(i) .. ')' end,
200 ['unsigned short int'] = function(i) return 'lua_isnumber(L, ' .. tostring(i) .. ')' end,
201 ['int'] = function(i) return 'lua_tointeger(L, ' .. tostring(i) .. ')' end,
202 ['unsigned int'] = function(i) return 'lua_isnumber(L, ' .. tostring(i) .. ')' end,
203 ['long int'] = function(i) return 'lua_isnumber(L, ' .. tostring(i) .. ')' end,
204 ['unsigned long int'] = function(i) return 'lua_isnumber(L, ' .. tostring(i) .. ')' end,
205 ['long long int'] = function(i) return 'lua_isnumber(L, ' .. tostring(i) .. ')' end,
206 ['unsigned long long int'] = function(i) return 'lua_isnumber(L, ' .. tostring(i) .. ')' end,
207 ['float'] = function(i) return 'lua_isnumber(L, ' .. tostring(i) .. ')' end,
208 ['double'] = function(i) return 'lua_isnumber(L, ' .. tostring(i) .. ')' end,
209 ['bool'] = function(i) return 'lua_isboolean(L, ' .. tostring(i) .. ')' end,
210 ['void *'] = function(i) return 'lua_isuserdata(L, ' .. tostring(i) .. ')' end,
211 ['void * *'] = function(i) return 'lua_isuserdata(L, ' .. tostring(i) .. ')' end,
214 -- more precise integer test
215 -- function(i) return '(lua_isnumber(L, ' .. tostring(i) .. ') && (lua_tointeger(L, ' .. tostring(i) .. ') == lua_tonumber(L, ' .. tostring(i) .. ')))' end,
217 setmetatable(type_on_stack_test, type_on_stack_test_mt)
218 type_on_stack_test_mt.__call = function (t, el, i)
219 print ('TESTING ARGUMENT', i)
220 local name = type_name(el)
221 -- if t[el] then return t[el] end
222 if type(type_on_stack_test_mt[name])=='function' then
223 t[el] = type_on_stack_test_mt[name](i)
224 else
225 if (el.tag=='Class') then
226 t[el] = 'luaL_testudata(L, ' .. tostring(i) .. ', "' .. name .. '*")'
227 elseif (el.tag=='CvQualifiedType') then
228 t[el] = t(find_id(el.attr.type), i)
229 elseif (el.tag=='ReferenceType') then
230 t[el] = t(find_id(el.attr.type), i)
231 elseif (el.tag=='PointerType') then
232 t[el] = t(find_id(el.attr.type), i)
233 elseif (el.tag=='Enumeration') then
234 t[el] = 'luaL_isenum(L, '..tostring(i)..', "'..name..'")'
237 print (el.tag, el, rawget(t,el) or '<>')
238 return rawget(t,el) or '<>'
243 cpairs = function (t, c)
244 return function (table, key, val)
245 key, val = next(table, key, val)
246 while not c(val) and key~=nil do key, val = next(table, key, val) end
247 return key, val
248 end, t
253 ------------------ MAIN PROGRAM ----------------------
255 my_class = find_name(my_typename)
257 if not my_members then
258 my_members = {}
259 for s in string.gmatch(my_class.attr.members, '(_%d+) ') do
260 print("member found:", s)
261 table.insert(my_members, find(xmlt, id_search(s)))
265 public_members = {}
266 for i, m in pairs(my_members) do
267 if m.attr.access=='public' then
268 table.insert( public_members, m )
273 getarg = function (a, n, i, def)
274 local ret = ''
275 local a_t = a.attr.id
276 local argtype = type_name(a)
277 print ('getting arg type', argtype, a_t)
278 ret = ret .. ' ' .. argtype .. ' ' .. n .. ' = '
279 .. (def and (type_on_stack_test(a, i) .. '?') or '') .. type_from_stack(a, i)
280 ret = ret .. (def and (':' .. tostring(def)) or '') .. '; // '..tostring(def)..'\n'
281 return ret
284 function pointer_search(id)
285 return function(t)
286 return (type(t)=='table') and (t.tag=='PointerType') and (type(t.attr)=='table') and (t.attr.type==id)
290 function function_body(p, n)
291 local ret = ''
292 local isstatic = 0
294 ret = ret .. 'static int ' .. n .. '(lua_State *L) {\n'
297 if p.attr.static~='1' then
298 -- ret = ret .. ' ' .. my_typename .. ' *__lua__obj = *static_cast<' .. my_typename
299 -- .. '**>(luaL_checkudata(L, 1, "'.. my_typename .. '**"));\n'
300 ret = ret .. getarg( find(xmlt, pointer_search(my_class.attr.id)) or error'FUCK!', '__lua__obj', 1)
301 -- print (ret)
302 isstatic = 1
305 local args = {}
306 for argi = 1, table.maxn(p) do
307 if (type(p[argi])=='table') and (p[argi].tag=='Argument') then
308 table.insert(args, p[argi])
312 for argi = 1, table.maxn(args) do
313 local arg = args[argi]
314 local argname = 'arg' .. tostring(argi)
315 if (type(arg)=='table') and (arg.tag=='Argument') then
316 local def = arg.attr.default or nil
317 local argt = find_id(arg.attr.type)
318 if def and find_id(arg.attr.type).tag=='Enumeration' then
319 local cont = find_id(argt.attr.context).attr.name
320 def = ((cont=='::') and '' or (cont .. '::')) .. def
322 ret = ret .. getarg(argt, argname, argi+isstatic, def)
326 if p.attr.static~='1' then
327 ret = ret .. ' __lua__obj->' .. p.attr.name .. '('
328 if table.maxn(args) > 0 then ret = ret .. 'arg1' end
329 for argi = 2, table.maxn(args) do
330 ret = ret .. ', arg' .. tostring(argi)
332 ret = ret .. ');\n'
333 else
334 ret = ret .. p.attr.name .. '('
335 if table.maxn(args) > 0 then ret = ret .. 'arg1' end
336 for argi = 2, table.maxn(args) do
337 ret = ret .. ', arg' .. tostring(argi)
339 ret = ret .. ');\n'
342 ret = ret .. ' return 1;\n'
343 ret = ret .. '}\n'
345 return ret
349 function function_test(p, score)
350 local ret = ''
351 local isstatic = 0
353 ret = ret .. ' ' .. score .. ' = 0;\n'
355 if p.attr.static~='1' then
356 ret = ret .. ' ' .. score .. ' += ' .. type_on_stack_test( find(xmlt, pointer_search(my_class.attr.id)), 1 )
357 .. '?premium:-premium*premium;\n'
358 isstatic = 1
361 local args = {}
362 for argi = 1, table.maxn(p) do
363 if (type(p[argi])=='table') and (p[argi].tag=='Argument') then
364 table.insert(args, p[argi])
368 for argi = 1, table.maxn(args) do
369 local arg = args[argi]
370 print ( 'ARGUMENT TEST', argi)
371 local argname = 'arg' .. tostring(argi)
372 if (type(arg)=='table') and (arg.tag=='Argument') then
373 ret = ret .. ' if (' .. type_on_stack_test( find_id(arg.attr.type) , argi+isstatic ) .. ') {\n'
374 ret = ret .. ' ' .. score .. ' += premium;\n'
375 ret = ret .. ' } else if (' .. tostring(arg.attr.default and true or false) .. ') {\n'
376 ret = ret .. ' ' .. score .. ' += premium-1; // '..tostring(arg, arg.attr.default)..';\n'
377 ret = ret .. ' } else {\n'
378 ret = ret .. ' ' .. score .. ' -= premium*premium;\n'
379 ret = ret .. ' }\n'
381 -- ret = ret .. ' ' .. score .. ' += ' .. type_on_stack_test( find_id(arg.attr.type) , argi+isstatic )
382 -- .. '?' .. tostring(premium) .. ':-' .. tostring(premium) .. '*' .. tostring(premium) .. ';\n'
386 -- print ('|||||||||||||||||||', ret)
387 return ret
395 hpp_text = hpp_text .. [[
397 static int luaL_toenum(lua_State *L, int index, const char *name) {
398 int ret;
399 lua_getfield(L, LUA_REGISTRYINDEX, "Enumerations");
401 if (!lua_istable(L, -1)) { lua_pop(L, 1); return -1; }
403 lua_pushstring(L, name);
404 lua_gettable(L, -2);
405 lua_remove(L, -2);
407 if (!lua_istable(L, -1)) { lua_pop(L, 1); return -1; }
409 lua_pushvalue(L, index);
410 lua_gettable(L, -2);
411 lua_remove(L, -2);
413 ret = lua_tointeger(L, -1);
415 lua_pop(L, 1);
417 return ret;
420 static bool luaL_isenum(lua_State *L, int index, const char *name) {
421 bool ret;
422 lua_getfield(L, LUA_REGISTRYINDEX, "Enumerations");
424 if (!lua_istable(L, -1)) { lua_pop(L, 1); return false; }
426 lua_pushstring(L, name);
427 lua_gettable(L, -2);
428 lua_remove(L, -2);
430 if (!lua_istable(L, -1)) { lua_pop(L, 1); return false; }
432 lua_pushvalue(L, index);
433 lua_gettable(L, -2);
434 lua_remove(L, -2);
436 ret = (bool)lua_isnumber(L, -1);
438 lua_pop(L, 1);
440 return ret;
443 static bool luaL_testudata(lua_State *L, int index, const char *name) {
444 bool ret = false;
445 lua_getmetatable(L, index);
446 lua_getfield(L, LUA_REGISTRYINDEX, name);
447 ret = (bool)lua_equal(L, -1, -2);
448 lua_pop(L, 2);
449 return ret;
454 hpp_text = hpp_text .. 'class LuaWrap' .. my_typename .. ': public ' .. my_typename .. ' {\n'
456 hpp_text = hpp_text .. 'public:\n'
458 overloaded_public = {}
459 for i, p in pairs(public_members) do
460 print('=========EXAMINING MEMBER==========', i)
461 if p.tag=='Method' then
462 if overloaded_public[p.attr.name]==nil then
463 overloaded_public[p.attr.name] = { p }
464 else
465 table.insert(overloaded_public[p.attr.name], p)
467 else
471 for n, l in pairs(overloaded_public) do
472 print('=========MAKING METHOD==========', n)
473 if table.maxn(l) == 1 then
474 -- print(l, l[1])
475 hpp_text = hpp_text .. function_body(l[1], 'LuaCallWrap__'..n)
476 else
477 local dispatcher = 'static int '..'LuaWrapCall__'..n..'(lua_State *L) {\n'
478 dispatcher = dispatcher .. ' int scores['..tostring(table.maxn(l))..'];\n'
479 dispatcher = dispatcher .. ' const int premium = 11+lua_gettop(L);\n'
481 for j = 1, table.maxn(l) do
482 hpp_text = hpp_text .. function_body(l[j], 'LuaCallWrap__'..n..'__LuaOverloadedVersion__'..j)
483 local test = function_test(l[j], 'scores['..j..']', table.maxn(l)+11)
484 dispatcher = dispatcher .. test
485 print (test)
488 dispatcher = dispatcher .. ' int best = 1;\n'
489 dispatcher = dispatcher .. ' for (int i=1;i<='.. table.maxn(l) ..';i++) {\n'
490 dispatcher = dispatcher .. ' if (scores[best] < scores[i]) { best = i; }\n'
491 dispatcher = dispatcher .. ' }\n'
492 dispatcher = dispatcher .. ' switch (best) {\n'
493 for j = 1, table.maxn(l) do
494 dispatcher = dispatcher .. ' case ' .. tostring(j) .. ': return ' .. 'LuaCallWrap__'..n..'__LuaOverloadedVersion__'..j..'(L); break;\n'
496 dispatcher = dispatcher .. ' }\n'
498 dispatcher = dispatcher .. '};\n'
500 hpp_text = hpp_text .. dispatcher
504 hpp_text = hpp_text .. 'private:\n'
506 hpp_text = hpp_text .. 'protected:\n'
507 hpp_text = hpp_text .. ' lua_State *L;\n'
508 hpp_text = hpp_text .. '};'
510 --[[
511 hpp_text = hpp_text .. '\n'
512 hpp_text = hpp_text .. 'class LuaWrap' .. my_typename .. ': public ' .. my_typename .. ' {\n'
513 hpp_text = hpp_text .. 'private:\n' .. hpp_public
514 hpp_text = hpp_text .. 'private:\n' .. hpp_private
515 hpp_text = hpp_text .. 'protected:\n' .. hpp_protected
516 hpp_text = hpp_text .. '};'
517 --]]