Lua: Don't lua_error() out of context with pending dtors
[lsnes.git] / src / library / lua.cpp
blobb83387bb95107580c6fb2795866d79e079adf1ea
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 try {
215 std::string name = lua_tostring(L, lua_upvalueindex(3));
216 state _L(*lstate, L);
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 try {
232 state _L(*lstate, L);
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 L.pushglobals();
246 assert(L.type(-1) == LUA_TTABLE);
247 return;
249 std::string u = tab;
250 size_t split = u.find_last_of(".");
251 std::string u1;
252 std::string u2 = u;
253 if(split < u.length()) {
254 u1 = u.substr(0, split);
255 u2 = u.substr(split + 1);
257 recursive_lookup_table(L, u1);
258 L.getfield(-1, u2.c_str());
259 if(L.type(-1) != LUA_TTABLE) {
260 //Not a table, create a table.
261 L.pop(1);
262 L.newtable();
263 L.setfield(-2, u2.c_str());
264 L.getfield(-1, u2.c_str());
266 //Get rid of previous table.
267 L.insert(-2);
268 L.pop(1);
271 void register_function(state& L, const std::string& name, function* fun)
273 std::string u = name;
274 size_t split = u.find_last_of(".");
275 std::string u1;
276 std::string u2 = u;
277 if(split < u.length()) {
278 u1 = u.substr(0, split);
279 u2 = u.substr(split + 1);
281 recursive_lookup_table(L, u1);
282 if(!fun)
283 L.pushnil();
284 else {
285 void* ptr = reinterpret_cast<void*>(fun);
286 L.pushlightuserdata(ptr);
287 L.pushlightuserdata(&L);
288 L.pushcclosure(lua_trampoline_function, 2);
290 L.setfield(-2, u2.c_str());
291 L.pop(1);
294 void register_class(state& L, const std::string& name, class_base* fun)
296 fun->register_state(L);
300 state::state() throw(std::bad_alloc)
302 master = NULL;
303 lua_handle = NULL;
304 oom_handler = builtin_oom;
307 state::state(state& _master, lua_State* L)
309 master = &_master;
310 lua_handle = L;
313 state::~state() throw()
315 if(master)
316 return;
317 threads::arlock h(get_lua_lock());
318 auto state = state_internal_t::get_soft(this);
319 if(!state) return;
320 for(auto i : state->function_groups)
321 i.first->drop_callback(i.second);
322 for(auto i : state->class_groups)
323 i.first->drop_callback(i.second);
324 if(lua_handle)
325 lua_close(lua_handle);
326 state_internal_t::clear(this);
329 void state::builtin_oom()
331 std::cerr << "PANIC: FATAL: Out of memory" << std::endl;
332 exit(1);
335 void* state::builtin_alloc(void* user, void* old, size_t olds, size_t news)
337 if(news) {
338 void* m = realloc(old, news);
339 if(!m)
340 reinterpret_cast<state*>(user)->oom_handler();
341 return m;
342 } else
343 free(old);
344 return NULL;
348 function::function(function_group& _group, const std::string& func) throw(std::bad_alloc)
349 : group(_group)
351 group.do_register(fname = func, *this);
354 function::~function() throw()
356 group.do_unregister(fname, *this);
359 class_base::class_base(class_group& _group, const std::string& _name)
360 : group(_group), name(_name)
362 registered = false;
365 class_base::~class_base() throw()
367 if(registered)
368 group.do_unregister(name, *this);
371 void state::reset() throw(std::bad_alloc, std::runtime_error)
373 if(master)
374 return master->reset();
375 threads::arlock h(get_lua_lock());
376 auto state = &state_internal_t::get(this);
377 if(lua_handle) {
378 lua_State* tmp = lua_newstate(state::builtin_alloc, this);
379 if(!tmp)
380 throw std::runtime_error("Can't re-initialize Lua interpretter");
381 lua_close(lua_handle);
382 for(auto& i : state->callbacks)
383 i.second->clear();
384 lua_handle = tmp;
385 } else {
386 //Initialize new.
387 lua_handle = lua_newstate(state::builtin_alloc, this);
388 if(!lua_handle)
389 throw std::runtime_error("Can't initialize Lua interpretter");
391 for(auto i : state->function_groups)
392 i.first->request_callback([this](std::string name, function* func) -> void {
393 register_function(*this, name, func);
395 for(auto i : state->class_groups)
396 i.first->request_callback([this](std::string name, class_base* clazz) -> void {
397 register_class(*this, name, clazz);
401 void state::deinit() throw()
403 if(master)
404 return master->deinit();
405 if(lua_handle)
406 lua_close(lua_handle);
407 lua_handle = NULL;
410 void state::add_function_group(function_group& group)
412 threads::arlock h(get_lua_lock());
413 auto& state = state_internal_t::get(this);
414 state.function_groups.insert(std::make_pair(&group, group.add_callback([this](const std::string& name,
415 function* func) -> void {
416 this->function_callback(name, func);
417 }, [this](function_group* x) {
418 threads::arlock h(get_lua_lock());
419 auto state = state_internal_t::get_soft(this);
420 if(!state) return;
421 for(auto i = state->function_groups.begin(); i != state->function_groups.end();)
422 if(i->first == x)
423 i = state->function_groups.erase(i);
424 else
425 i++;
426 })));
429 void state::add_class_group(class_group& group)
431 threads::arlock h(get_lua_lock());
432 auto& state = state_internal_t::get(this);
433 state.class_groups.insert(std::make_pair(&group, group.add_callback([this](const std::string& name,
434 class_base* clazz) -> void {
435 this->class_callback(name, clazz);
436 }, [this](class_group* x) {
437 threads::arlock h(get_lua_lock());
438 auto state = state_internal_t::get_soft(this);
439 if(!state) return;
440 for(auto i = state->class_groups.begin(); i != state->class_groups.end();)
441 if(i->first == x)
442 i = state->class_groups.erase(i);
443 else
444 i++;
445 })));
448 void state::function_callback(const std::string& name, function* func)
450 if(master)
451 return master->function_callback(name, func);
452 if(lua_handle)
453 register_function(*this, name, func);
456 void state::class_callback(const std::string& name, class_base* clazz)
458 if(master)
459 return master->class_callback(name, clazz);
460 if(lua_handle)
461 register_class(*this, name, clazz);
464 bool state::do_once(void* key)
466 if(master)
467 return master->do_once(key);
468 pushlightuserdata(key);
469 rawget(LUA_REGISTRYINDEX);
470 if(type(-1) == LUA_TNIL) {
471 pop(1);
472 pushlightuserdata(key);
473 pushlightuserdata(key);
474 rawset(LUA_REGISTRYINDEX);
475 return true;
476 } else {
477 pop(1);
478 return false;
482 std::list<state::callback_list*> state::get_callbacks()
484 if(master)
485 return master->get_callbacks();
486 threads::arlock h(get_lua_lock());
487 auto state = state_internal_t::get_soft(this);
488 std::list<callback_list*> r;
489 if(state)
490 for(auto i : state->callbacks)
491 r.push_back(i.second);
492 return r;
495 void state::do_register(const std::string& name, callback_list& callback)
497 threads::arlock h(get_lua_lock());
498 auto& state = state_internal_t::get(this);
499 if(state.callbacks.count(name)) return;
500 state.callbacks[name] = &callback;
503 void state::do_unregister(const std::string& name, callback_list& callback)
505 threads::arlock h(get_lua_lock());
506 auto state = state_internal_t::get_soft(this);
507 if(state && state->callbacks.count(name) && state->callbacks[name] == &callback)
508 state->callbacks.erase(name);
511 state::callback_list::callback_list(state& _L, const std::string& _name, const std::string& fncbname)
512 : L(_L), name(_name), fn_cbname(fncbname)
514 L.do_register(name, *this);
517 state::callback_list::~callback_list()
519 L.do_unregister(name, *this);
520 if(!L.handle())
521 return;
522 for(auto& i : callbacks) {
523 L.pushlightuserdata(&i);
524 L.pushnil();
525 L.rawset(LUA_REGISTRYINDEX);
529 void state::callback_list::_register(state& _L)
531 callbacks.push_back(0);
532 _L.pushlightuserdata(&*callbacks.rbegin());
533 _L.pushvalue(-2);
534 _L.rawset(LUA_REGISTRYINDEX);
537 void state::callback_list::_unregister(state& _L)
539 for(auto i = callbacks.begin(); i != callbacks.end();) {
540 _L.pushlightuserdata(&*i);
541 _L.rawget(LUA_REGISTRYINDEX);
542 if(_L.rawequal(-1, -2)) {
543 char* key = &*i;
544 _L.pushlightuserdata(key);
545 _L.pushnil();
546 _L.rawset(LUA_REGISTRYINDEX);
547 i = callbacks.erase(i);
548 } else
549 i++;
550 _L.pop(1);
554 function_group::function_group()
558 function_group::~function_group()
560 threads::arlock h(get_lua_lock());
561 auto state = fgroup_internal_t::get_soft(this);
562 if(!state) return;
563 for(auto i : state->dcallbacks)
564 i.second(this);
565 fgroup_internal_t::clear(this);
568 void function_group::request_callback(std::function<void(std::string, function*)> cb)
570 threads::arlock h(get_lua_lock());
571 auto state = fgroup_internal_t::get_soft(this);
572 if(!state) return;
573 for(auto i : state->functions)
574 cb(i.first, i.second);
577 int function_group::add_callback(std::function<void(std::string, function*)> cb,
578 std::function<void(function_group*)> dcb)
580 threads::arlock h(get_lua_lock());
581 auto& state = fgroup_internal_t::get(this);
582 int handle = state.next_handle++;
583 state.callbacks[handle] = cb;
584 state.dcallbacks[handle] = dcb;
585 for(auto i : state.functions)
586 cb(i.first, i.second);
587 return handle;
590 void function_group::drop_callback(int handle)
592 threads::arlock h(get_lua_lock());
593 auto state = fgroup_internal_t::get_soft(this);
594 if(!state) return;
595 state->callbacks.erase(handle);
598 void function_group::do_register(const std::string& name, function& fun)
600 threads::arlock h(get_lua_lock());
601 auto& state = fgroup_internal_t::get(this);
602 if(state.functions.count(name)) return;
603 state.functions[name] = &fun;
604 for(auto i : state.callbacks)
605 i.second(name, &fun);
608 void function_group::do_unregister(const std::string& name, function& fun)
610 threads::arlock h(get_lua_lock());
611 auto state = fgroup_internal_t::get_soft(this);
612 if(!state || !state->functions.count(name) || state->functions[name] != &fun) return;
613 state->functions.erase(name);
614 for(auto i : state->callbacks)
615 i.second(name, NULL);
618 class_group::class_group()
622 class_group::~class_group()
624 threads::arlock h(get_lua_lock());
625 auto state = cgroup_internal_t::get_soft(this);
626 if(!state) return;
627 for(auto i : state->dcallbacks)
628 i.second(this);
629 cgroup_internal_t::clear(this);
632 void class_group::request_callback(std::function<void(std::string, class_base*)> cb)
634 threads::arlock h(get_lua_lock());
635 auto state = cgroup_internal_t::get_soft(this);
636 if(!state) return;
637 for(auto i : state->classes)
638 cb(i.first, i.second);
641 int class_group::add_callback(std::function<void(std::string, class_base*)> cb,
642 std::function<void(class_group*)> dcb)
644 threads::arlock h(get_lua_lock());
645 auto& state = cgroup_internal_t::get(this);
646 int handle = state.next_handle++;
647 state.callbacks[handle] = cb;
648 state.dcallbacks[handle] = dcb;
649 for(auto i : state.classes)
650 cb(i.first, i.second);
651 return handle;
654 void class_group::drop_callback(int handle)
656 threads::arlock h(get_lua_lock());
657 auto state = cgroup_internal_t::get_soft(this);
658 if(!state) return;
659 state->callbacks.erase(handle);
662 void class_group::do_register(const std::string& name, class_base& fun)
664 threads::arlock h(get_lua_lock());
665 auto& state = cgroup_internal_t::get(this);
666 if(state.classes.count(name)) return;
667 state.classes[name] = &fun;
668 for(auto i : state.callbacks)
669 i.second(name, &fun);
672 void class_group::do_unregister(const std::string& name, class_base& fun)
674 threads::arlock h(get_lua_lock());
675 auto state = cgroup_internal_t::get_soft(this);
676 if(!state || !state->classes.count(name) || state->classes[name] != &fun) return;
677 state->classes.erase(name);
678 for(auto i : state->callbacks)
679 i.second(name, NULL);
682 std::list<class_ops>& userdata_recogn_fns()
684 static std::list<class_ops> x;
685 return x;
688 std::string try_recognize_userdata(state& state, int index)
690 for(auto i : userdata_recogn_fns())
691 if(i.is(state, index))
692 return i.name();
693 //Hack: Lua builtin file objects and classobjs.
694 if(state.getmetatable(index)) {
695 state.pushstring("FILE*");
696 state.rawget(LUA_REGISTRYINDEX);
697 if(state.rawequal(-1, -2)) {
698 state.pop(2);
699 return "FILE*";
701 state.pop(1);
702 state.pushlightuserdata(&classtable_meta_key);
703 state.rawget(LUA_REGISTRYINDEX);
704 if(state.rawequal(-1, -2)) {
705 state.pop(2);
706 return "classobj";
708 state.pop(1);
710 return "unknown";
713 std::string try_print_userdata(state& L, int index)
715 for(auto i : userdata_recogn_fns())
716 if(i.is(L, index))
717 return i.print(L, index);
718 //Hack: classobjs.
719 if(L.getmetatable(index)) {
720 L.pushlightuserdata(&classtable_meta_key);
721 L.rawget(LUA_REGISTRYINDEX);
722 if(L.rawequal(-1, -2)) {
723 L.pop(2);
724 std::string cname = ((class_info*)L.touserdata(index))->obj->get_name();
725 return cname;
727 L.pop(1);
729 return "no data available";
732 int state::vararg_tag::pushargs(state& L)
734 int e = 0;
735 for(auto i : args) {
736 if(i == "")
737 L.pushnil();
738 else if(i == "true")
739 L.pushboolean(true);
740 else if(i == "false")
741 L.pushboolean(false);
742 else if(regex_match("[+-]?(|0|[1-9][0-9]*)(.[0-9]+)?([eE][+-]?(0|[1-9][0-9]*))?", i))
743 L.pushnumber(strtod(i.c_str(), NULL));
744 else if(i[0] == ':')
745 L.pushlstring(i.substr(1));
746 else
747 L.pushlstring(i);
748 e++;
750 return e;
753 class_base* class_base::lookup(state& L, const std::string& _name)
755 if(lookup_and_push(L, _name)) {
756 class_base* obj = ((class_info*)L.touserdata(-1))->obj;
757 L.pop(1);
758 return obj;
760 return NULL;
763 bool class_base::lookup_and_push(state& L, const std::string& _name)
765 L.pushlightuserdata(&classtable_key);
766 L.rawget(LUA_REGISTRYINDEX);
767 if(L.type(-1) == LUA_TNIL) {
768 //No classes.
769 L.pop(1);
770 return false;
772 //On top of stack there is class table.
773 L.pushlstring(_name);
774 L.rawget(-2);
775 if(L.type(-1) == LUA_TNIL) {
776 //Not found.
777 L.pop(2);
778 return false;
780 L.insert(-2);
781 L.pop(1);
782 return true;
785 std::set<std::string> class_base::all_classes(state& L)
787 L.pushlightuserdata(&classtable_key);
788 L.rawget(LUA_REGISTRYINDEX);
789 if(L.type(-1) == LUA_TNIL) {
790 //No classes.
791 L.pop(1);
792 return std::set<std::string>();
794 std::set<std::string> r;
795 L.pushnil();
796 while(L.next(-2)) {
797 L.pop(1); //Pop value.
798 if(L.type(-1) == LUA_TSTRING) r.insert(L.tostring(-1));
800 L.pop(1);
801 return r;
804 void class_base::register_static(state& L)
806 again:
807 L.pushlightuserdata(&classtable_key);
808 L.rawget(LUA_REGISTRYINDEX);
809 if(L.type(-1) == LUA_TNIL) {
810 L.pop(1);
811 L.pushlightuserdata(&classtable_key);
812 L.newtable();
813 L.rawset(LUA_REGISTRYINDEX);
814 goto again;
816 //On top of stack there is class table.
817 L.pushlstring(name);
818 L.rawget(-2);
819 if(L.type(-1) != LUA_TNIL) {
820 //Already registered.
821 L.pop(2);
822 return;
824 L.pop(1);
825 L.pushlstring(name);
826 //Now construct the object.
827 class_info* ci = (class_info*)L.newuserdata(sizeof(class_info));
828 ci->obj = this;
829 again2:
830 L.pushlightuserdata(&classtable_meta_key);
831 L.rawget(LUA_REGISTRYINDEX);
832 if(L.type(-1) == LUA_TNIL) {
833 L.pop(1);
834 L.pushlightuserdata(&classtable_meta_key);
835 L.newtable();
836 L.pushstring("__index");
837 L.pushlightuserdata(&L);
838 L.pushcclosure(class_info::index, 1);
839 L.rawset(-3);
840 L.pushstring("__newindex");
841 L.pushcfunction(class_info::newindex);
842 L.rawset(-3);
843 L.pushstring("__pairs");
844 L.pushlightuserdata(&L);
845 L.pushcclosure(class_info::pairs, 1);
846 L.rawset(-3);
847 L.rawset(LUA_REGISTRYINDEX);
848 goto again2;
850 L.setmetatable(-2);
851 L.rawset(-3);
852 L.pop(1);
855 void class_base::delayed_register()
857 group.do_register(name, *this);
860 functions::functions(function_group& grp, const std::string& basetable, std::initializer_list<entry> fnlist)
862 std::string base = (basetable == "") ? "" : (basetable + ".");
863 for(auto i : fnlist)
864 funcs.insert(new fn(grp, base + i.name, i.func));
867 functions::~functions()
869 for(auto i : funcs)
870 delete i;
873 functions::fn::fn(function_group& grp, const std::string& name, std::function<int(state& L, parameters& P)> _func)
874 : function(grp, name)
876 func = _func;
879 functions::fn::~fn() throw()
883 int functions::fn::invoke(state& L)
885 lua::parameters P(L, fname);
886 return func(L, P);