+ lua_pushcclosure(state_, function, upvalues);
+ return top();
+ }
+
+ template <class T>
+ slot push_class_metatable()
+ {
+ bool is_new;
+ slot metatable = push_metatable(typeid(T).name(), is_new);
+ if (is_new)
+ {
+ metatable.push_copy(); // class behavior
+ metatable.set_field("__index");
+ push_type<T>();
+ metatable.set_field("__cxxtype"); // type_info
+ push(object_finalizer_<T>);
+ metatable.set_field("__gc"); // finalizer
+ //push(object_tostring_<T>);
+ //metatable.set_field("__tostring"); // tostring
+ }
+ return metatable;
+ }
+
+ template <class T>
+ static int object_tostring_(lua_State* state)
+ {
+ std::ostringstream stream;
+ stream << *reinterpret_cast<T*>(lua_touserdata(state, 1));
+ lua_pushlstring(state,
+ stream.str().c_str(), stream.str().length());
+ return 1;
+ }
+
+ template <class T>
+ static int object_finalizer_(lua_State* state)
+ {
+ reinterpret_cast<T*>(lua_touserdata(state, 1))->~T();
+ return 0;
+ }
+
+ static int call_functor(lua_State* state)
+ {
+ function* function = (script::function*)lua_touserdata(state,
+ lua_upvalueindex(1));
+
+ script* script = (moof::script*)lua_touserdata(state,
+ lua_upvalueindex(2));
+
+ try
+ {
+ return (*function)(*script);
+ }
+ catch (const std::exception& e)
+ {
+ if (0 < std::strlen(e.what()))
+ {
+ luaL_where(state, 1);
+ lua_pushstring(state, e.what());
+ lua_concat(state, 2);
+ }
+ return lua_error(state);
+ }
+ catch (const char* e)
+ {
+ luaL_where(state, 1);
+ lua_pushstring(state, e);
+ lua_concat(state, 2);
+ return lua_error(state);
+ }
+ catch (...)
+ {
+ return lua_error(state);
+ }
+ }
+
+ static int call_function(lua_State* state)
+ {
+ cfunction function = (cfunction)lua_touserdata(state,