Lua.cpp: Get rid of register-queue
[lsnes.git] / src / library / lua.cpp
blob0c333d7220b72a79b0906e33f457d2466adf156f
1 #include "lua-base.hpp"
2 #include "lua-class.hpp"
3 #include "lua-function.hpp"
4 #include "lua-params.hpp"
5 #include "lua-pin.hpp"
6 #include "stateobject.hpp"
7 #include "threads.hpp"
8 #include <iostream>
9 #include <cassert>
11 namespace lua
13 namespace
15 threads::rlock* global_lock;
16 threads::rlock& get_lua_lock()
18 if(!global_lock) global_lock = new threads::rlock;
19 return *global_lock;
22 struct state_internal
24 std::map<std::string, state::callback_list*> callbacks;
25 std::set<std::pair<function_group*, int>> function_groups;
26 std::set<std::pair<class_group*, int>> class_groups;
29 struct fgroup_internal
31 fgroup_internal()
33 next_handle = 0;
35 std::map<std::string, function*> functions;
36 int next_handle;
37 std::map<int, std::function<void(std::string, function*)>> callbacks;
38 std::map<int, std::function<void(function_group*)>> dcallbacks;
41 struct cgroup_internal
43 cgroup_internal()
45 next_handle = 0;
47 int next_handle;
48 std::map<std::string, class_base*> classes;
49 std::map<int, std::function<void(std::string, class_base*)>> callbacks;
50 std::map<int, std::function<void(class_group*)>> dcallbacks;
53 typedef stateobject::type<state, state_internal> state_internal_t;
54 typedef stateobject::type<function_group, fgroup_internal> fgroup_internal_t;
55 typedef stateobject::type<class_group, cgroup_internal> cgroup_internal_t;
58 std::unordered_map<std::type_index, void*>& class_types()
60 static std::unordered_map<std::type_index, void*> x;
61 return x;
63 namespace
65 char classtable_key;
66 char classtable_meta_key;
68 struct class_info
70 class_base* obj;
71 static int index(lua_State* L);
72 static int newindex(lua_State* L);
73 static int pairs(lua_State* L);
74 static int pairs_next(lua_State* L);
75 static int smethods(lua_State* L);
76 static int cmethods(lua_State* L);
77 static int trampoline(lua_State* L);
78 static void check(lua_State* L);
81 void class_info::check(lua_State* L)
83 lua_pushlightuserdata(L, &classtable_meta_key);
84 lua_rawget(L, LUA_REGISTRYINDEX);
85 lua_getmetatable(L, 1);
86 if(!lua_rawequal(L, -1, -2)) {
87 lua_pushstring(L, "Bad class table");
88 lua_error(L);
90 lua_pop(L, 2);
93 int class_info::index(lua_State* L)
95 check(L);
97 class_base* ptr = ((class_info*)lua_touserdata(L, 1))->obj;
98 const char* method = lua_tostring(L, 2);
99 if(!method) {
100 lua_pushstring(L, "Indexing invalid element of class table");
101 lua_error(L);
103 if(!strcmp(method, "_static_methods")) {
104 lua_pushlightuserdata(L, ptr);
105 lua_pushcclosure(L, class_info::smethods, 1);
106 return 1;
107 } else if(!strcmp(method, "_class_methods")) {
108 lua_pushlightuserdata(L, ptr);
109 lua_pushcclosure(L, class_info::cmethods, 1);
110 return 1;
111 } else {
112 auto m = ptr->static_methods();
113 for(auto i : m) {
114 if(!strcmp(i.name, method)) {
115 //Hit.
116 std::string name = ptr->get_name() + "::" + method;
117 lua_pushvalue(L, lua_upvalueindex(1)); //State.
118 lua_pushlightuserdata(L, (void*)i.fn);
119 std::string fname = ptr->get_name() + "::" + i.name;
120 lua_pushstring(L, fname.c_str());
121 lua_pushcclosure(L, class_info::trampoline, 3);
122 return 1;
125 std::string err = std::string("Class '") + ptr->get_name() +
126 "' does not have static method '" + method + "'";
127 lua_pushstring(L, err.c_str());
128 lua_error(L);
130 return 0; //NOTREACHED
132 int class_info::newindex(lua_State* L)
134 lua_pushstring(L, "Writing into class table not allowed");
135 lua_error(L);
136 return 0; //NOTREACHED
139 int class_info::pairs(lua_State* _xL)
141 check(_xL);
143 lua::state* _L = (lua::state*)lua_touserdata(_xL, lua_upvalueindex(1));
144 state L(*_L, _xL);
146 L.pushvalue(lua_upvalueindex(1));
147 L.pushcclosure(class_info::pairs_next, 1); //Next
148 L.pushvalue(1); //State.
149 L.pushnil(); //Index.
150 return 3;
153 int class_info::pairs_next(lua_State* _xL)
155 check(_xL);
157 lua::state* _L = (lua::state*)lua_touserdata(_xL, lua_upvalueindex(1));
158 state L(*_L, _xL);
159 class_base* obj = ((class_info*)L.touserdata(1))->obj;
160 auto m = obj->static_methods();
161 std::string key = (L.type(2) == LUA_TSTRING) ? L.tostring(2) : "";
162 std::string lowbound = "\xFF"; //Sorts greater than anything that is valid UTF-8.
163 void* best_fn = NULL;
164 for(auto i : m)
165 if(lowbound > i.name && i.name > key) {
166 lowbound = i.name;
167 best_fn = (void*)i.fn;
169 if(best_fn) {
170 L.pushlstring(lowbound);
171 std::string name = obj->get_name() + "::" + lowbound;
172 L.pushvalue(lua_upvalueindex(1)); //State.
173 L.pushlightuserdata(best_fn);
174 L.pushlstring(name);
175 L.pushcclosure(class_info::trampoline, 3);
176 return 2;
177 } else {
178 L.pushnil();
179 return 1;
183 int class_info::smethods(lua_State* L)
185 class_base* obj = (class_base*)lua_touserdata(L, lua_upvalueindex(1));
186 auto m = obj->static_methods();
187 int rets = 0;
188 for(auto i : m) {
189 lua_pushstring(L, i.name);
190 rets++;
192 return rets;
195 int class_info::cmethods(lua_State* L)
197 class_base* obj = (class_base*)lua_touserdata(L, lua_upvalueindex(1));
198 auto m = obj->class_methods();
199 int rets = 0;
200 for(auto i : m) {
201 lua_pushstring(L, i.c_str());
202 rets++;
204 return rets;
207 typedef int (*fn_t)(state& L, parameters& P);
209 int class_info::trampoline(lua_State* L)
211 state* lstate = reinterpret_cast<state*>(lua_touserdata(L, lua_upvalueindex(1)));
212 void* _fn = lua_touserdata(L, lua_upvalueindex(2));
213 fn_t fn = (fn_t)_fn;
214 std::string name = lua_tostring(L, lua_upvalueindex(3));
215 state _L(*lstate, L);
216 try {
217 parameters P(_L, name);
218 return fn(_L, P);
219 } catch(std::exception& e) {
220 lua_pushfstring(L, "%s", e.what());
221 lua_error(L);
223 return 0;
226 int lua_trampoline_function(lua_State* L)
228 void* ptr = lua_touserdata(L, lua_upvalueindex(1));
229 state* lstate = reinterpret_cast<state*>(lua_touserdata(L, lua_upvalueindex(2)));
230 function* f = reinterpret_cast<function*>(ptr);
231 state _L(*lstate, L);
232 try {
233 return f->invoke(_L);
234 } catch(std::exception& e) {
235 lua_pushfstring(L, "%s", e.what());
236 lua_error(L);
238 return 0;
241 //Pushes given table to top of stack, creating if needed.
242 void recursive_lookup_table(state& L, const std::string& tab)
244 if(tab == "") {
245 #if LUA_VERSION_NUM == 501
246 L.pushvalue(LUA_GLOBALSINDEX);
247 #endif
248 #if LUA_VERSION_NUM == 502
249 L.rawgeti(LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
250 #endif
251 assert(L.type(-1) == LUA_TTABLE);
252 return;
254 std::string u = tab;
255 size_t split = u.find_last_of(".");
256 std::string u1;
257 std::string u2 = u;
258 if(split < u.length()) {
259 u1 = u.substr(0, split);
260 u2 = u.substr(split + 1);
262 recursive_lookup_table(L, u1);
263 L.getfield(-1, u2.c_str());
264 if(L.type(-1) != LUA_TTABLE) {
265 //Not a table, create a table.
266 L.pop(1);
267 L.newtable();
268 L.setfield(-2, u2.c_str());
269 L.getfield(-1, u2.c_str());
271 //Get rid of previous table.
272 L.insert(-2);
273 L.pop(1);
276 void register_function(state& L, const std::string& name, function* fun)
278 std::string u = name;
279 size_t split = u.find_last_of(".");
280 std::string u1;
281 std::string u2 = u;
282 if(split < u.length()) {
283 u1 = u.substr(0, split);
284 u2 = u.substr(split + 1);
286 recursive_lookup_table(L, u1);
287 if(!fun)
288 L.pushnil();
289 else {
290 void* ptr = reinterpret_cast<void*>(fun);
291 L.pushlightuserdata(ptr);
292 L.pushlightuserdata(&L);
293 L.pushcclosure(lua_trampoline_function, 2);
295 L.setfield(-2, u2.c_str());
296 L.pop(1);
299 void register_class(state& L, const std::string& name, class_base* fun)
301 fun->register_state(L);
305 state::state() throw(std::bad_alloc)
307 master = NULL;
308 lua_handle = NULL;
309 oom_handler = builtin_oom;
312 state::state(state& _master, lua_State* L)
314 master = &_master;
315 lua_handle = L;
318 state::~state() throw()
320 if(master)
321 return;
322 threads::arlock h(get_lua_lock());
323 auto state = state_internal_t::get_soft(this);
324 if(!state) return;
325 for(auto i : state->function_groups)
326 i.first->drop_callback(i.second);
327 for(auto i : state->class_groups)
328 i.first->drop_callback(i.second);
329 if(lua_handle)
330 lua_close(lua_handle);
331 state_internal_t::clear(this);
334 void state::builtin_oom()
336 std::cerr << "PANIC: FATAL: Out of memory" << std::endl;
337 exit(1);
340 void* state::builtin_alloc(void* user, void* old, size_t olds, size_t news)
342 if(news) {
343 void* m = realloc(old, news);
344 if(!m)
345 reinterpret_cast<state*>(user)->oom_handler();
346 return m;
347 } else
348 free(old);
349 return NULL;
353 function::function(function_group& _group, const std::string& func) throw(std::bad_alloc)
354 : group(_group)
356 group.do_register(fname = func, *this);
359 function::~function() throw()
361 group.do_unregister(fname, *this);
364 class_base::class_base(class_group& _group, const std::string& _name)
365 : group(_group), name(_name)
367 registered = false;
370 class_base::~class_base() throw()
372 if(registered)
373 group.do_unregister(name, *this);
376 void state::reset() throw(std::bad_alloc, std::runtime_error)
378 if(master)
379 return master->reset();
380 threads::arlock h(get_lua_lock());
381 auto state = state_internal_t::get_soft(this);
382 if(!state) return;
383 if(lua_handle) {
384 lua_State* tmp = lua_newstate(state::builtin_alloc, this);
385 if(!tmp)
386 throw std::runtime_error("Can't re-initialize Lua interpretter");
387 lua_close(lua_handle);
388 for(auto& i : state->callbacks)
389 i.second->clear();
390 lua_handle = tmp;
391 } else {
392 //Initialize new.
393 lua_handle = lua_newstate(state::builtin_alloc, this);
394 if(!lua_handle)
395 throw std::runtime_error("Can't initialize Lua interpretter");
397 for(auto i : state->function_groups)
398 i.first->request_callback([this](std::string name, function* func) -> void {
399 register_function(*this, name, func);
401 for(auto i : state->class_groups)
402 i.first->request_callback([this](std::string name, class_base* clazz) -> void {
403 register_class(*this, name, clazz);
407 void state::deinit() throw()
409 if(master)
410 return master->deinit();
411 if(lua_handle)
412 lua_close(lua_handle);
413 lua_handle = NULL;
416 void state::add_function_group(function_group& group)
418 threads::arlock h(get_lua_lock());
419 auto& state = state_internal_t::get(this);
420 state.function_groups.insert(std::make_pair(&group, group.add_callback([this](const std::string& name,
421 function* func) -> void {
422 this->function_callback(name, func);
423 }, [this](function_group* x) {
424 threads::arlock h(get_lua_lock());
425 auto state = state_internal_t::get_soft(this);
426 if(!state) return;
427 for(auto i = state->function_groups.begin(); i != state->function_groups.end();)
428 if(i->first == x)
429 i = state->function_groups.erase(i);
430 else
431 i++;
432 })));
435 void state::add_class_group(class_group& group)
437 threads::arlock h(get_lua_lock());
438 auto& state = state_internal_t::get(this);
439 state.class_groups.insert(std::make_pair(&group, group.add_callback([this](const std::string& name,
440 class_base* clazz) -> void {
441 this->class_callback(name, clazz);
442 }, [this](class_group* x) {
443 threads::arlock h(get_lua_lock());
444 auto state = state_internal_t::get_soft(this);
445 if(!state) return;
446 for(auto i = state->class_groups.begin(); i != state->class_groups.end();)
447 if(i->first == x)
448 i = state->class_groups.erase(i);
449 else
450 i++;
451 })));
454 void state::function_callback(const std::string& name, function* func)
456 if(master)
457 return master->function_callback(name, func);
458 if(lua_handle)
459 register_function(*this, name, func);
462 void state::class_callback(const std::string& name, class_base* clazz)
464 if(master)
465 return master->class_callback(name, clazz);
466 if(lua_handle)
467 register_class(*this, name, clazz);
470 bool state::do_once(void* key)
472 if(master)
473 return master->do_once(key);
474 pushlightuserdata(key);
475 rawget(LUA_REGISTRYINDEX);
476 if(type(-1) == LUA_TNIL) {
477 pop(1);
478 pushlightuserdata(key);
479 pushlightuserdata(key);
480 rawset(LUA_REGISTRYINDEX);
481 return true;
482 } else {
483 pop(1);
484 return false;
488 std::list<state::callback_list*> state::get_callbacks()
490 if(master)
491 return master->get_callbacks();
492 threads::arlock h(get_lua_lock());
493 auto state = state_internal_t::get_soft(this);
494 std::list<callback_list*> r;
495 if(state)
496 for(auto i : state->callbacks)
497 r.push_back(i.second);
498 return r;
501 void state::do_register(const std::string& name, callback_list& callback)
503 threads::arlock h(get_lua_lock());
504 auto& state = state_internal_t::get(this);
505 if(state.callbacks.count(name)) return;
506 state.callbacks[name] = &callback;
509 void state::do_unregister(const std::string& name, callback_list& callback)
511 threads::arlock h(get_lua_lock());
512 auto state = state_internal_t::get_soft(this);
513 if(state && state->callbacks.count(name) && state->callbacks[name] == &callback)
514 state->callbacks.erase(name);
517 state::callback_list::callback_list(state& _L, const std::string& _name, const std::string& fncbname)
518 : L(_L), name(_name), fn_cbname(fncbname)
520 L.do_register(name, *this);
523 state::callback_list::~callback_list()
525 L.do_unregister(name, *this);
526 if(!L.handle())
527 return;
528 for(auto& i : callbacks) {
529 L.pushlightuserdata(&i);
530 L.pushnil();
531 L.rawset(LUA_REGISTRYINDEX);
535 void state::callback_list::_register(state& _L)
537 callbacks.push_back(0);
538 _L.pushlightuserdata(&*callbacks.rbegin());
539 _L.pushvalue(-2);
540 _L.rawset(LUA_REGISTRYINDEX);
543 void state::callback_list::_unregister(state& _L)
545 for(auto i = callbacks.begin(); i != callbacks.end();) {
546 _L.pushlightuserdata(&*i);
547 _L.rawget(LUA_REGISTRYINDEX);
548 if(_L.rawequal(-1, -2)) {
549 char* key = &*i;
550 _L.pushlightuserdata(key);
551 _L.pushnil();
552 _L.rawset(LUA_REGISTRYINDEX);
553 i = callbacks.erase(i);
554 } else
555 i++;
556 _L.pop(1);
560 function_group::function_group()
564 function_group::~function_group()
566 threads::arlock h(get_lua_lock());
567 auto state = fgroup_internal_t::get_soft(this);
568 if(!state) return;
569 for(auto i : state->dcallbacks)
570 i.second(this);
571 fgroup_internal_t::clear(this);
574 void function_group::request_callback(std::function<void(std::string, function*)> cb)
576 threads::arlock h(get_lua_lock());
577 auto state = fgroup_internal_t::get_soft(this);
578 if(!state) return;
579 for(auto i : state->functions)
580 cb(i.first, i.second);
583 int function_group::add_callback(std::function<void(std::string, function*)> cb,
584 std::function<void(function_group*)> dcb)
586 threads::arlock h(get_lua_lock());
587 auto& state = fgroup_internal_t::get(this);
588 int handle = state.next_handle++;
589 state.callbacks[handle] = cb;
590 state.dcallbacks[handle] = dcb;
591 for(auto i : state.functions)
592 cb(i.first, i.second);
593 return handle;
596 void function_group::drop_callback(int handle)
598 threads::arlock h(get_lua_lock());
599 auto state = fgroup_internal_t::get_soft(this);
600 if(!state) return;
601 state->callbacks.erase(handle);
604 void function_group::do_register(const std::string& name, function& fun)
606 threads::arlock h(get_lua_lock());
607 auto& state = fgroup_internal_t::get(this);
608 if(state.functions.count(name)) return;
609 state.functions[name] = &fun;
610 for(auto i : state.callbacks)
611 i.second(name, &fun);
614 void function_group::do_unregister(const std::string& name, function& fun)
616 threads::arlock h(get_lua_lock());
617 auto state = fgroup_internal_t::get_soft(this);
618 if(!state) return;
619 if(state && state->functions.count(name) && state->functions[name] == &fun)
620 state->functions.erase(name);
621 for(auto i : state->callbacks)
622 i.second(name, NULL);
625 class_group::class_group()
629 class_group::~class_group()
631 threads::arlock h(get_lua_lock());
632 auto state = cgroup_internal_t::get_soft(this);
633 if(!state) return;
634 for(auto i : state->dcallbacks)
635 i.second(this);
636 cgroup_internal_t::clear(this);
639 void class_group::request_callback(std::function<void(std::string, class_base*)> cb)
641 threads::arlock h(get_lua_lock());
642 auto state = cgroup_internal_t::get_soft(this);
643 if(!state) return;
644 for(auto i : state->classes)
645 cb(i.first, i.second);
648 int class_group::add_callback(std::function<void(std::string, class_base*)> cb,
649 std::function<void(class_group*)> dcb)
651 threads::arlock h(get_lua_lock());
652 auto& state = cgroup_internal_t::get(this);
653 int handle = state.next_handle++;
654 state.callbacks[handle] = cb;
655 state.dcallbacks[handle] = dcb;
656 for(auto i : state.classes)
657 cb(i.first, i.second);
658 return handle;
661 void class_group::drop_callback(int handle)
663 threads::arlock h(get_lua_lock());
664 auto state = cgroup_internal_t::get_soft(this);
665 if(!state) return;
666 state->callbacks.erase(handle);
669 void class_group::do_register(const std::string& name, class_base& fun)
671 threads::arlock h(get_lua_lock());
672 auto& state = cgroup_internal_t::get(this);
673 if(state.classes.count(name)) return;
674 state.classes[name] = &fun;
675 for(auto i : state.callbacks)
676 i.second(name, &fun);
679 void class_group::do_unregister(const std::string& name, class_base& fun)
681 threads::arlock h(get_lua_lock());
682 auto state = cgroup_internal_t::get_soft(this);
683 if(!state || !state->classes.count(name) || state->classes[name] != &fun) return;
684 state->classes.erase(name);
685 for(auto i : state->callbacks)
686 i.second(name, NULL);
689 std::list<class_ops>& userdata_recogn_fns()
691 static std::list<class_ops> x;
692 return x;
695 std::string try_recognize_userdata(state& state, int index)
697 for(auto i : userdata_recogn_fns())
698 if(i.is(state, index))
699 return i.name();
700 //Hack: Lua builtin file objects and classobjs.
701 if(state.getmetatable(index)) {
702 state.pushstring("FILE*");
703 state.rawget(LUA_REGISTRYINDEX);
704 if(state.rawequal(-1, -2)) {
705 state.pop(2);
706 return "FILE*";
708 state.pop(1);
709 state.pushlightuserdata(&classtable_meta_key);
710 state.rawget(LUA_REGISTRYINDEX);
711 if(state.rawequal(-1, -2)) {
712 state.pop(2);
713 return "classobj";
715 state.pop(1);
717 return "unknown";
720 std::string try_print_userdata(state& L, int index)
722 for(auto i : userdata_recogn_fns())
723 if(i.is(L, index))
724 return i.print(L, index);
725 //Hack: classobjs.
726 if(L.getmetatable(index)) {
727 L.pushlightuserdata(&classtable_meta_key);
728 L.rawget(LUA_REGISTRYINDEX);
729 if(L.rawequal(-1, -2)) {
730 L.pop(2);
731 std::string cname = ((class_info*)L.touserdata(index))->obj->get_name();
732 return cname;
734 L.pop(1);
736 return "no data available";
739 int state::vararg_tag::pushargs(state& L)
741 int e = 0;
742 for(auto i : args) {
743 if(i == "")
744 L.pushnil();
745 else if(i == "true")
746 L.pushboolean(true);
747 else if(i == "false")
748 L.pushboolean(false);
749 else if(regex_match("[+-]?(|0|[1-9][0-9]*)(.[0-9]+)?([eE][+-]?(0|[1-9][0-9]*))?", i))
750 L.pushnumber(strtod(i.c_str(), NULL));
751 else if(i[0] == ':')
752 L.pushlstring(i.substr(1));
753 else
754 L.pushlstring(i);
755 e++;
757 return e;
760 class_base* class_base::lookup(state& L, const std::string& _name)
762 if(lookup_and_push(L, _name)) {
763 class_base* obj = ((class_info*)L.touserdata(-1))->obj;
764 L.pop(1);
765 return obj;
767 return NULL;
770 bool class_base::lookup_and_push(state& L, const std::string& _name)
772 L.pushlightuserdata(&classtable_key);
773 L.rawget(LUA_REGISTRYINDEX);
774 if(L.type(-1) == LUA_TNIL) {
775 //No classes.
776 L.pop(1);
777 return false;
779 //On top of stack there is class table.
780 L.pushlstring(_name);
781 L.rawget(-2);
782 if(L.type(-1) == LUA_TNIL) {
783 //Not found.
784 L.pop(2);
785 return false;
787 L.insert(-2);
788 L.pop(1);
789 return true;
792 std::set<std::string> class_base::all_classes(state& L)
794 L.pushlightuserdata(&classtable_key);
795 L.rawget(LUA_REGISTRYINDEX);
796 if(L.type(-1) == LUA_TNIL) {
797 //No classes.
798 L.pop(1);
799 return std::set<std::string>();
801 std::set<std::string> r;
802 L.pushnil();
803 while(L.next(-2)) {
804 L.pop(1); //Pop value.
805 if(L.type(-1) == LUA_TSTRING) r.insert(L.tostring(-1));
807 L.pop(1);
808 return r;
811 void class_base::register_static(state& L)
813 again:
814 L.pushlightuserdata(&classtable_key);
815 L.rawget(LUA_REGISTRYINDEX);
816 if(L.type(-1) == LUA_TNIL) {
817 L.pop(1);
818 L.pushlightuserdata(&classtable_key);
819 L.newtable();
820 L.rawset(LUA_REGISTRYINDEX);
821 goto again;
823 //On top of stack there is class table.
824 L.pushlstring(name);
825 L.rawget(-2);
826 if(L.type(-1) != LUA_TNIL) {
827 //Already registered.
828 L.pop(2);
829 return;
831 L.pop(1);
832 L.pushlstring(name);
833 //Now construct the object.
834 class_info* ci = (class_info*)L.newuserdata(sizeof(class_info));
835 ci->obj = this;
836 again2:
837 L.pushlightuserdata(&classtable_meta_key);
838 L.rawget(LUA_REGISTRYINDEX);
839 if(L.type(-1) == LUA_TNIL) {
840 L.pop(1);
841 L.pushlightuserdata(&classtable_meta_key);
842 L.newtable();
843 L.pushstring("__index");
844 L.pushlightuserdata(&L);
845 L.pushcclosure(class_info::index, 1);
846 L.rawset(-3);
847 L.pushstring("__newindex");
848 L.pushcfunction(class_info::newindex);
849 L.rawset(-3);
850 L.pushstring("__pairs");
851 L.pushlightuserdata(&L);
852 L.pushcclosure(class_info::pairs, 1);
853 L.rawset(-3);
854 L.rawset(LUA_REGISTRYINDEX);
855 goto again2;
857 L.setmetatable(-2);
858 L.rawset(-3);
859 L.pop(1);
862 void class_base::delayed_register()
864 group.do_register(name, *this);
867 functions::functions(function_group& grp, const std::string& basetable, std::initializer_list<entry> fnlist)
869 std::string base = (basetable == "") ? "" : (basetable + ".");
870 for(auto i : fnlist)
871 funcs.insert(new fn(grp, base + i.name, i.func));
874 functions::~functions()
876 for(auto i : funcs)
877 delete i;
880 functions::fn::fn(function_group& grp, const std::string& name, std::function<int(state& L, parameters& P)> _func)
881 : function(grp, name)
883 func = _func;
886 functions::fn::~fn() throw()
890 int functions::fn::invoke(state& L)
892 lua::parameters P(L, fname);
893 return func(L, P);