Make typesystem global variable
[lqt/mk.git] / generator / classes.lua
blobd1470270ec9c9bf3eb4a8a90e2e82adb5285f1de
1 require 'virtuals'
2 require 'templates'
3 require 'operators'
4 require 'signalslot'
6 module('classes', package.seeall)
8 local functions = {}
9 local classes = {}
10 local cpp_files = {}
12 --- Copies functions from the index.
13 function copy_functions(index)
14 for e in pairs(index) do
15 if e.label:match'^Function' then
16 e.label = 'Function'
17 functions[e] = true
18 end
19 end
20 end
23 function fix_arguments(index)
24 for a in pairs(index) do
25 if a.label=='Argument'
26 and a.xarg.default=='1'
27 and (not string.match(a.xarg.defaultvalue, '^[-+]?%d+%.?%d*[L]?$'))
28 and (not string.match(a.xarg.defaultvalue, '^".*"$'))
29 and a.xarg.defaultvalue~='true'
30 and a.xarg.defaultvalue~='false'
31 and (not string.match(a.xarg.defaultvalue, '^0[xX]%d+$')) then
32 local dv, call = string.match(a.xarg.defaultvalue, '(.-)(%(%))')
33 dv = dv or a.xarg.defaultvalue
34 call = call or ''
35 local context = a.xarg.context
36 while not fullnames[context..'::'..dv] and context~='' do
37 context = string.match(context, '^(.*)::') or ''
38 end
39 if fullnames[context..'::'..dv] then
40 if fullnames[context..'::'..dv].xarg.name==fullnames[context..'::'..dv].xarg.member_of_class then
41 context = string.match(context, '^(.*)::') or ''
42 end
43 a.xarg.defaultvalue = context..'::'..dv..call
44 elseif fullnames[dv] then
45 a.xarg.defaultvalue = dv..call
46 else
47 a.xarg.default = nil
48 a.xarg.defaultvalue = nil
49 end
50 end
51 end
52 end
55 --- Removes unneeded 'void' parameters and return values.
56 function fix_functions()
57 for f in pairs(functions) do
58 local args = {}
59 for i, a in ipairs(f) do
60 -- avoid bogus 'void' arguments
61 if a.xarg.type_name=='void' and i==1 and f[2]==nil then break end
62 if a.label=='Argument' then
63 table.insert(args, a)
64 end
65 end
66 f.arguments = args
67 f.return_type = f.xarg.type_name
68 if f.xarg.type_name=='void' then
69 f.return_type = nil
70 end
71 end
72 end
74 --- Determines, if a class is public.
75 function class_is_public(c)
76 repeat
77 if c.xarg.access~='public' then return false end
78 if c.xarg.member_of_class then
79 local p = fullnames[c.xarg.member_of_class]
80 assert(p, 'member_of_class should exist')
81 assert(p.label=='Class', 'member_of_class should be a class')
82 c = fullnames[c.xarg.member_of_class]
83 else
84 return true
85 end
86 until true
87 end
89 --- Selects public classes from the index, and creates templated instances
90 -- where appropriate.
91 function copy_classes(index)
92 for e in pairs(index) do
93 if e.label=='Class' then
94 e.xarg.safename = e.xarg.fullname
95 if class_is_public(e)
96 and not e.xarg.fullname:match'%b<>' then
97 classes[e] = true
98 elseif not e.xarg.fullname:match'%b<>' then
99 ignore(e.xarg.fullname, 'not public')
100 else
101 if templates.should_copy(e) then
102 templates.create(e, classes)
107 templates.finish(index)
110 function fix_methods_wrappers()
111 for c in pairs(classes) do
112 c.shell = c.public_destr
113 c.shell = c.shell and (next(c.virtuals)~=nil)
114 for _, constr in ipairs(c.constructors) do
115 if c.shell then
116 local shellname = 'lqt_shell_'..string.gsub(c.xarg.safename, '::', '_LQT_')
117 constr.calling_line = 'new '..shellname..'(L'
118 if #(constr.arguments)>0 then constr.calling_line = constr.calling_line .. ', ' end
119 else
120 local shellname = c.xarg.fullname
121 constr.calling_line = 'new '..shellname..'('
123 for i=1,#(constr.arguments) do
124 constr.calling_line = constr.calling_line .. (i==1 and '' or ', ') .. 'arg' .. i
126 constr.calling_line = '*('..constr.calling_line .. '))'
127 constr.xarg.static = '1'
128 constr.return_type = constr.xarg.scope..'&'
130 if c.destructor then
131 c.destructor.return_type = nil
136 --- Determines, whether classes are children of QObject.
137 -- Fills the 'qobject' field on class if it is child of QObject.
138 function get_qobjects()
139 local function is_qobject(c)
140 if c==nil then return false end
141 if c.qobject then return true end
142 if c.xarg.fullname=='QObject' then
143 c.qobject = true
144 return true
146 for b in string.gmatch(c.xarg.bases or '', '([^;]+);') do
147 local base = fullnames[b]
148 if is_qobject(base) then
149 --debug(c.xarg.fullname, "is a QObject")
150 c.qobject = true
151 return true
154 return false
156 for c in pairs(classes) do
157 local qobj = is_qobject(c)
163 local should_wrap = function(f)
164 local name = f.xarg.name
165 -- unfixed operator and friend, causes trouble with QDataStream
166 -- if f.xarg.friend and #f.arguments ==2 then return false end
167 -- not an operator - accept
168 if not name:match('^operator') then return true end
169 -- accept supported operators
170 if operators.is_operator(name) then return true end
171 return false
176 function distinguish_methods()
177 for c in pairs(classes) do
178 local construct, destruct, normal = {}, nil, {}
179 local n = c.xarg.name:gsub('%b<>', '')
181 local copy = nil
182 for _, f in ipairs(c) do
183 if n==f.xarg.name then
184 table.insert(construct, f)
185 elseif f.xarg.name:match'~' then
186 destruct = f
187 else
188 if should_wrap(f)
189 and (not f.xarg.member_template_parameters) then
190 table.insert(normal, f)
191 else
192 ignore(f.xarg.fullname, 'operator/template/friend', c.xarg.name)
196 c.constructors = construct
197 c.destructor = destruct
198 c.methods = normal
202 --- Determines, if a class has a public destructor. It also scans the superclasses.
203 -- Sets the 'public_destr' fiield on the class.
204 function fill_public_destr()
205 local function destr_is_public(c)
206 if c.destructor then
207 return c.destructor.xarg.access=='public'
208 else
209 for b in string.gmatch(c.xarg.bases or '', '([^;]+);') do
210 local base = fullnames[b]
211 if base and not destr_is_public(base) then
212 return false
215 return true
218 for c in pairs(classes) do
219 c.public_destr = destr_is_public(c)
224 function generate_default_copy_constructor(c)
225 if not c.xarg then return end
227 local copy = {
228 [1] = {
229 label = "Argument";
230 xarg = {
231 context = c.xarg.name;
232 id = next_id();
233 name = "p";
234 scope = "";
235 type_base = c.xarg.name;
236 type_constant = "1";
237 type_name = c.xarg.name .. " const&";
238 type_reference = "1";
241 label = "Function";
242 return_type = c.xarg.name;
243 xarg = {
244 access = "public";
245 context = c.xarg.name;
246 fullname = c.xarg.name.."::"..c.xarg.name;
247 id = next_id();
248 inline = "1";
249 member_of = c.xarg.name;
250 member_of_class = c.xarg.name;
251 name = c.xarg.name;
252 scope = c.xarg.name;
253 type_base = c.xarg.name;
254 type_name = c.xarg.name;
257 copy.arguments = {copy[1]}
259 table.insert(c, copy)
260 table.insert(c.constructors, copy)
261 functions[copy] = true
263 return copy
266 -- HACK: do not create copy contructors for classes, that
267 -- contain variables of class '*Private' - they will not compile
268 -- in Qt 4.6
269 local function has_private_fields(c)
270 for _,v in ipairs(c) do
271 if v.label == 'Variable' then
272 if v.xarg.type_base:match('Private') then
273 ignore(c.xarg.fullname, 'cannot create copy constructor', v.xarg.fullname .. ' : ' ..v.xarg.type_base)
274 return true
278 return false
281 function fill_copy_constructor()
282 for c in pairs(classes) do
283 local copy = nil
284 for _, f in ipairs(c.constructors) do
285 if #(f.arguments)==1
286 and f.arguments[1].xarg.type_name==c.xarg.fullname..' const&' then
287 copy = f
288 break
291 c.copy_constructor = copy
293 local function copy_constr_is_public(c)
294 if c.copy_constructor then
295 return (c.copy_constructor.xarg.access=='public')
296 or (c.copy_constructor.xarg.access=='protected')
297 else
298 if has_private_fields(c) then return false end
299 local ret = nil
300 for b in string.gmatch(c.xarg.bases or '', '([^;]+);') do
301 local base = fullnames[b]
302 if base and not copy_constr_is_public(base) then
303 return false
306 return true
309 for c in pairs(classes) do
310 c.public_constr = copy_constr_is_public(c)
311 if c.public_constr and not c.copy_constructor then
312 c.copy_constructor = generate_default_copy_constructor(c)
318 local put_class_in_filesystem = lqt.classes.insert
320 function fill_typesystem_with_classes()
321 for c in pairs(classes) do
322 classes[c] = put_class_in_filesystem(c.xarg.fullname) --, true)
327 function fill_wrapper_code(f)
328 if f.wrapper_code then return f end
329 local stackn, argn = 1, 1
330 local stack_args, defects = '', 0
331 local has_args = true
332 local wrap, line = ' int oldtop = lua_gettop(L);\n', ''
333 if f.xarg.abstract then
334 ignore(f.xarg.fullname, 'abstract method', f.xarg.member_of_class)
335 return nil
337 if f.xarg.member_of_class and f.xarg.static~='1' then
338 if not typesystem[f.xarg.member_of_class..'*'] then
339 ignore(f.xarg.fullname, 'not a member of wrapped class', f.xarg.member_of_class)
340 return nil
342 stack_args = stack_args .. typesystem[f.xarg.member_of_class..'*'].onstack
343 defects = defects + 7 -- FIXME: arbitrary
344 if f.xarg.constant=='1' then
345 defects = defects + 8 -- FIXME: arbitrary
347 local sget, sn = typesystem[f.xarg.member_of_class..'*'].get(stackn)
348 wrap = wrap .. ' ' .. f.xarg.member_of_class .. '* self = ' .. sget .. ';\n'
349 stackn = stackn + sn
350 wrap = wrap .. [[
351 if (NULL==self) {
352 lua_pushfstring(L, "Instance of %s has already been deleted in:\n", "]]..f.xarg.member_of_class..[[");
353 lqtL_pushtrace(L);
354 lua_concat(L, 2);
355 lua_error(L);
358 --print(sget, sn)
359 if operators.is_operator(f.xarg.name) then
360 line, has_args = operators.call_line(f)
361 if not line then return nil end
362 else
363 line = 'self->'..f.xarg.fullname..'('
365 else
366 line = f.xarg.fullname..'('
368 for i, a in ipairs(f.arguments) do
369 if not typesystem[a.xarg.type_name] then
370 ignore(f.xarg.fullname, 'unkown argument type', a.xarg.type_name)
371 return nil
373 local aget, an, arg_as = typesystem[a.xarg.type_name].get(stackn)
374 stack_args = stack_args .. typesystem[a.xarg.type_name].onstack
375 if typesystem[a.xarg.type_name].defect then defects = defects + typesystem[a.xarg.type_name].defect end
376 wrap = wrap .. ' ' .. argument_name(arg_as or a.xarg.type_name, 'arg'..argn) .. ' = '
377 if a.xarg.default=='1' and an>0 then
378 wrap = wrap .. 'lua_isnoneornil(L, '..stackn..')'
379 for j = stackn+1,stackn+an-1 do
380 wrap = wrap .. ' && lua_isnoneornil(L, '..j..')'
382 local dv = a.xarg.defaultvalue
383 wrap = wrap .. ' ? static_cast< ' .. a.xarg.type_name .. ' >(' .. dv .. ') : '
385 wrap = wrap .. aget .. ';\n'
386 line = line .. (argn==1 and 'arg' or ', arg') .. argn
387 stackn = stackn + an
388 argn = argn + 1
390 if has_args then
391 line = line .. ')'
393 -- FIXME: hack follows for constructors
394 if f.calling_line then line = f.calling_line end
395 if f.return_type then line = f.return_type .. ' ret = ' .. line end
396 wrap = wrap .. ' ' .. line .. ';\n lua_settop(L, oldtop);\n' -- lua_pop(L, '..stackn..');\n'
397 if f.return_type then
398 if not typesystem[f.return_type] then
399 ignore(f.xarg.fullname, 'unknown return type', f.return_type)
400 return nil
402 local rput, rn = typesystem[f.return_type].push'ret'
403 wrap = wrap .. ' luaL_checkstack(L, '..rn..', "cannot grow stack for return value");\n'
404 wrap = wrap .. ' '..rput..';\n return '..rn..';\n'
405 else
406 wrap = wrap .. ' return 0;\n'
408 f.wrapper_code = wrap
409 f.stack_arguments = stack_args
410 f.defects = defects
411 return f
415 function fill_test_code(f)
416 local stackn = 1
417 local test = ''
418 if f.xarg.member_of_class and f.xarg.static~='1' then
419 if not typesystem[f.xarg.member_of_class..'*'] then return nil end -- print(f.xarg.member_of_class) return nil end
420 local stest, sn = typesystem[f.xarg.member_of_class..'*'].test(stackn)
421 test = test .. ' && ' .. stest
422 stackn = stackn + sn
424 for i, a in ipairs(f.arguments) do
425 if not typesystem[a.xarg.type_name] then return nil end -- print(a.xarg.type_name) return nil end
426 local atest, an = typesystem[a.xarg.type_name].test(stackn)
427 if a.xarg.default=='1' and an>0 then
428 test = test .. ' && (lqtL_missarg(L, ' .. stackn .. ', ' .. an .. ') || '
429 test = test .. atest .. ')'
430 else
431 test = test .. ' && ' .. atest
433 stackn = stackn + an
435 -- can't make use of default values if I fix number of args
436 test = '(lua_gettop(L)<' .. stackn .. ')' .. test
437 f.test_code = test
438 return f
443 function fill_wrappers()
444 for f in pairs(functions) do
445 local nf = fill_wrapper_code(f)
446 if nf then
447 nf = assert(fill_test_code(nf), nf.xarg.fullname) -- MUST pass
448 else
449 -- failed to generate wrapper
450 functions[f] = nil
455 ---- Output functions
457 function print_wrappers()
458 for c in pairs(classes) do
459 local meta = {}
460 local wrappers = ''
461 for _, f in ipairs(c.methods) do
462 -- FIXME: should we really discard virtual functions?
463 -- if the virtual overload in the shell uses rawget
464 -- on the environment then we can leave these in the
465 -- metatable
466 if f.wrapper_code and not f.ignore then
467 local out = 'static int lqt_bind'..f.xarg.id
468 ..' (lua_State *L) {\n'.. f.wrapper_code .. '}\n'
469 if f.xarg.access=='public' then
470 --print_meta(out)
471 wrappers = wrappers .. out .. '\n'
472 meta[f] = f.xarg.name
476 if not c.abstract then
477 for _, f in ipairs(c.constructors) do
478 if f.wrapper_code then
479 local out = 'static int lqt_bind'..f.xarg.id
480 ..' (lua_State *L) {\n'.. f.wrapper_code .. '}\n'
481 if f.xarg.access=='public' then
482 --print_meta(out)
483 wrappers = wrappers .. out .. '\n'
484 meta[f] = 'new'
489 --local shellname = 'lqt_shell_'..string.gsub(c.xarg.fullname, '::', '_LQT_')
490 local lua_name = string.gsub(c.xarg.fullname, '::', '.')
491 local out = 'static int lqt_delete'..c.xarg.id..' (lua_State *L) {\n'
492 out = out ..' '..c.xarg.fullname..' *p = static_cast<'
493 ..c.xarg.fullname..'*>(lqtL_toudata(L, 1, "'..lua_name..'*"));\n'
494 if c.public_destr then
495 out = out .. ' if (p) delete p;\n'
497 out = out .. ' lqtL_eraseudata(L, 1, "'..lua_name..'*");\n return 0;\n}\n'
498 --print_meta(out)
499 wrappers = wrappers .. out .. '\n'
500 c.meta = meta
501 c.wrappers = wrappers
506 local print_metatable = function(c)
507 local methods = {}
508 local wrappers = c.wrappers
509 for m, n in pairs(c.meta) do
510 methods[n] = methods[n] or {}
511 table.insert(methods[n], m)
513 for n, l in pairs(methods) do
514 local duplicates = {}
515 for _, f in ipairs(l) do
516 if not f.ignore then
517 local itisnew = true
518 for sa, g in pairs(duplicates) do
519 if sa==f.stack_arguments then
520 --debug("function equal: ", f.xarg.fullname, f.stack_arguments, sa, f.defects, g.defects)
521 if f.defects<g.defects then
522 else
523 ignore(f.xarg.fullname, "duplicate function", f.stack_arguments)
524 itisnew = false
526 elseif string.match(sa, "^"..f.stack_arguments) then -- there is already a version with more arguments
527 --debug("function superseded: ", f.xarg.fullname, f.stack_arguments, sa, f.defects, g.defects)
528 elseif string.match(f.stack_arguments, '^'..sa) then -- there is already a version with less arguments
529 --debug("function superseding: ", f.xarg.fullname, f.stack_arguments, sa, f.defects, g.defects)
532 if itisnew then
533 duplicates[f.stack_arguments] = f
537 --[[
538 local numinitial = 0
539 local numfinal = 0
540 for sa, f in pairs(l) do
541 numinitial = numinitial + 1
543 for sa, f in pairs(duplicates) do
544 numfinal = numfinal + 1
546 if numinitial-numfinal>0 then debug(c.xarg.fullname, "suppressed:", numinitial-numfinal) end
547 --]]
548 methods[n] = duplicates
550 for n, l in pairs(methods) do
551 local name = operators.rename_operator(n)
552 local disp = 'static int lqt_dispatcher_'..name..c.xarg.id..' (lua_State *L) {\n'
553 local testcode = {}
554 for tc, f in pairs(l) do
555 disp = disp..' if ('..f.test_code..') return lqt_bind'..f.xarg.id..'(L);\n'
556 testcode[#testcode+1] = tc
558 -- disp = disp .. ' lua_settop(L, 0);\n'
559 disp = disp .. ' const char * args = lqtL_getarglist(L);\n'
560 disp = disp .. ' lua_pushfstring(L, "%s(%s): incorrect or extra arguments, expecting: %s.", "' ..
561 c.xarg.fullname..'::'..n..'", args, '..string.format("%q", table.concat(testcode, ' or ')) .. ');\n'
562 disp = disp .. ' return lua_error(L);\n}\n'
563 --print_meta(disp)
564 wrappers = wrappers .. disp .. '\n'
566 local metatable = 'static luaL_Reg lqt_metatable'..c.xarg.id..'[] = {\n'
567 for n, l in pairs(methods) do
568 local nn = operators.rename_operator(n)
569 metatable = metatable .. ' { "'..nn..'", lqt_dispatcher_'..nn..c.xarg.id..' },\n'
571 metatable = metatable .. ' { "delete", lqt_delete'..c.xarg.id..' },\n'
572 metatable = metatable .. ' { 0, 0 },\n};\n'
573 --print_meta(metatable)
574 wrappers = wrappers .. metatable .. '\n'
575 local bases = ''
576 for b in string.gmatch(c.xarg.bases_with_attributes or '', '([^;]*);') do
577 if not string.match(b, '^virtual') then
578 b = string.gsub(b, '^[^%s]* ', '')
579 bases = bases .. ' {"'..string.gsub(b,'::','.')..'*", (char*)(void*)static_cast<'..b..'*>(('..c.xarg.fullname..'*)1)-(char*)1},\n'
582 bases = 'static lqt_Base lqt_base'..c.xarg.id..'[] = {\n'..bases..' {NULL, 0}\n};\n'
583 --print_meta(bases)
584 wrappers = wrappers .. bases .. '\n'
585 c.wrappers = wrappers
586 return c
590 function print_metatables()
591 for c in pairs(classes) do
592 print_metatable(c)
597 function print_single_class(c)
598 local n = string.gsub(c.xarg.safename, '::', '_LQT_')
599 local lua_name = string.gsub(c.xarg.fullname, '::', '.')
600 local cppname = module_name..'_meta_'..n..'.cpp'
601 table.insert(cpp_files, cppname) -- global cpp_files
602 local fmeta = assert(io.open(module_name.._src..cppname, 'w'))
603 local print_meta = function(...)
604 fmeta:write(...)
605 fmeta:write'\n'
607 print_meta('#include "'..module_name..'_head_'..n..'.hpp'..'"\n\n')
608 print_meta(c.wrappers)
609 if c.virtual_overloads then
610 print_meta(c.virtual_overloads)
612 print_meta('extern "C" LQT_EXPORT int luaopen_'..n..' (lua_State *L) {')
613 print_meta('\tlqtL_createclass(L, "'
614 ..lua_name..'*", lqt_metatable'
615 ..c.xarg.id..', lqt_base'
616 ..c.xarg.id..');')
617 print_meta'\treturn 0;'
618 print_meta'}'
619 print_meta''
620 if c.shell and c.qobject then
621 print_meta([[
622 #include <QDebug>
624 QMetaObject lqt_shell_]]..n..[[::staticMetaObject;
626 const QMetaObject *lqt_shell_]]..n..[[::metaObject() const {
627 //int oldtop = lua_gettop(L);
628 lqtL_pushudata(L, this, "]]..c.xarg.fullname..[[*");
629 lua_getfield(L, -1, LQT_OBJMETASTRING);
630 if (lua_isnil(L, -1)) {
631 lua_pop(L, 2);
632 return &]]..c.xarg.fullname..[[::staticMetaObject;
634 lua_getfield(L, -2, LQT_OBJMETADATA);
635 lqtL_touintarray(L);
636 //qDebug() << "copying qmeta object for slots in ]]..c.xarg.fullname..[[";
637 lqt_shell_]]..n..[[::staticMetaObject.d.superdata = &]]..c.xarg.fullname..[[::staticMetaObject;
638 lqt_shell_]]..n..[[::staticMetaObject.d.stringdata = lua_tostring(L, -2);
639 lqt_shell_]]..n..[[::staticMetaObject.d.data = (uint*)lua_touserdata(L, -1);
640 lqt_shell_]]..n..[[::staticMetaObject.d.extradata = 0; // slot_metaobj->d.extradata;
641 lua_setfield(L, LUA_REGISTRYINDEX, LQT_OBJMETADATA);
642 lua_setfield(L, LUA_REGISTRYINDEX, LQT_OBJMETASTRING);
643 lua_pop(L, 1);
644 //qDebug() << (lua_gettop(L) - oldtop);
645 return &lqt_shell_]]..n..[[::staticMetaObject;
648 int lqt_shell_]]..n..[[::qt_metacall(QMetaObject::Call call, int index, void **args) {
649 //qDebug() << "fake calling!";
650 index = ]]..c.xarg.fullname..[[::qt_metacall(call, index, args);
651 if (index < 0) return index;
652 return lqtL_qt_metacall(L, this, lqtSlotAcceptor_]]..module_name..[[, call, "]]..c.xarg.fullname..[[*", index, args);
656 fmeta:close()
659 function print_merged_build()
660 local path = module_name.._src
661 local mergename = module_name..'_merged_build'
662 local merged = assert(io.open(path..mergename..'.cpp', 'w'))
663 for _, p in ipairs(cpp_files) do
664 merged:write('#include "'..p..'"\n')
666 local pro_file = assert(io.open(path..mergename..'.pro', 'w'))
668 local print_pro= function(...)
669 pro_file:write(...)
670 pro_file:write'\n'
672 print_pro('TEMPLATE = lib')
673 print_pro('TARGET = '..module_name)
674 print_pro('INCLUDEPATH += .')
675 print_pro('HEADERS += '..module_name..'_slot.hpp')
676 print_pro('SOURCES += ../common/lqt_common.cpp \\')
677 print_pro(' ../common/lqt_qt.cpp \\')
678 print_pro(' '..module_name..'_enum.cpp \\')
679 print_pro(' '..module_name..'_meta.cpp \\')
680 print_pro(' '..module_name..'_slot.cpp \\')
681 print_pro(' '..mergename..'.cpp')
685 function print_class_list()
686 local qobject_present = false
687 local big_picture = {}
688 local type_list_t = {}
689 for c in pairs(classes) do
690 local n = string.gsub(c.xarg.safename, '::', '_LQT_')
691 if n=='QObject' then qobject_present = true end
692 print_single_class(c)
693 table.insert(big_picture, 'luaopen_'..n)
694 table.insert(type_list_t, 'add_class(\''..c.xarg.fullname..'\', types)\n')
697 local type_list_f = assert(io.open(module_name.._src..module_name..'_types.lua', 'w'))
698 type_list_f:write([[
699 #!/usr/bin/lua
700 local types = (...) or {}
701 local add_class = lqt.classes.insert or error('module lqt.classes not loaded')
703 for k, v in ipairs(type_list_t) do
704 type_list_f:write(v)
706 type_list_f:write('return types\n')
707 type_list_f:close()
709 print_merged_build()
710 local fmeta = assert(io.open(module_name.._src..module_name..'_meta.cpp', 'w'))
711 local print_meta = function(...)
712 fmeta:write(...)
713 fmeta:write'\n'
715 print_meta()
716 print_meta('#include "lqt_common.hpp"')
717 print_meta('#include "'..module_name..'_slot.hpp'..'"\n\n')
718 for _, p in ipairs(big_picture) do
719 print_meta('extern "C" LQT_EXPORT int '..p..' (lua_State *);')
721 print_meta('void lqt_create_enums_'..module_name..' (lua_State *);')
722 print_meta('extern "C" LQT_EXPORT int luaopen_'..module_name..' (lua_State *L) {')
723 for _, p in ipairs(big_picture) do
724 print_meta('\t'..p..'(L);')
726 print_meta('\tlqt_create_enums_'..module_name..'(L);')
727 if qobject_present then
728 print_meta('\tlqtL_qobject_custom(L);')
730 print_meta('\t//lua_pushlightuserdata(L, (void*)&LqtSlotAcceptor::staticMetaObject);')
731 print_meta('\t//lua_setfield(L, LUA_REGISTRYINDEX, LQT_METAOBJECT);')
732 print_meta('\t//lqtL_passudata(L, (void*)(new LqtSlotAcceptor(L)), "QObject*");')
733 print_meta('\t//lua_setfield(L, LUA_REGISTRYINDEX, LQT_METACALLER);')
734 print_meta('\tlqtL_register_super(L);')
735 print_meta('\tlqtSlotAcceptor_'..module_name..' = new LqtSlotAcceptor(L);')
736 print_meta('\treturn 0;\n}')
737 if fmeta then fmeta:close() end
740 ------------------------------------------------------------
742 function preprocess(index)
743 copy_classes(index) -- picks classes if not private and not blacklisted
744 copy_functions(index) -- picks functions and fixes label
745 fix_arguments(index) -- fixes default arguments if they are context-relative
746 fix_functions() -- fixes name and fullname and fills arguments
747 operators.fix_operators(index)
750 function process(index, typesystem, filterfiles)
751 for _, f in ipairs(filterfiles) do
752 classes = loadfile(f)(classes)
755 fill_typesystem_with_classes()
757 virtuals.fill_virtuals(classes) -- does that, destructor ("~") excluded
758 distinguish_methods() -- does that
759 fill_public_destr() -- does that: checks if destructor is public
760 fill_copy_constructor() -- does that: checks if copy contructor is public or protected
761 fix_methods_wrappers()
762 get_qobjects()
764 fill_wrappers()
765 virtuals.fill_virtual_overloads(classes) -- does that
766 virtuals.fill_shell_classes(classes) -- does that
768 signalslot.process(functions)
771 function output()
772 virtuals.print_shell_classes(classes) -- does that, and outputs headers
773 virtuals.print_virtual_overloads(classes) -- does that
775 print_wrappers(classes) -- just compiles metatable list
776 print_metatables(classes) -- just collects the wrappers + generates dispatchers
777 print_class_list(classes) -- does that + prints everything related to class
779 signalslot.output()