Add missing scope::operator=.
[luabind.git] / src / class_rep.cpp
blob70bb6231cf1f7bf367d71f91f5b345f13729851e
1 // Copyright (c) 2003 Daniel Wallin and Arvid Norberg
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
23 #define LUABIND_BUILDING
25 #include <luabind/lua_include.hpp>
27 #include <luabind/detail/stack_utils.hpp>
28 #include <luabind/detail/conversion_storage.hpp>
29 #include <luabind/luabind.hpp>
30 #include <luabind/exception_handler.hpp>
31 #include <luabind/get_main_thread.hpp>
32 #include <utility>
34 using namespace luabind::detail;
36 namespace luabind { namespace detail
38 LUABIND_API int property_tag(lua_State* L)
40 lua_pushstring(L, "luabind: property_tag function can't be called");
41 lua_error(L);
42 return 0;
46 luabind::detail::class_rep::class_rep(type_id const& type
47 , const char* name
48 , lua_State* L
50 : m_type(type)
51 , m_name(name)
52 , m_class_type(cpp_class)
53 , m_operator_cache(0)
55 lua_newtable(L);
56 handle(L, -1).swap(m_table);
57 lua_newtable(L);
58 handle(L, -1).swap(m_default_table);
59 lua_pop(L, 2);
61 class_registry* r = class_registry::get_registry(L);
62 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
64 lua_rawgeti(L, LUA_REGISTRYINDEX, r->cpp_class());
65 lua_setmetatable(L, -2);
67 lua_pushvalue(L, -1); // duplicate our user data
68 m_self_ref.set(L);
70 m_instance_metatable = r->cpp_instance();
72 lua_pushstring(L, "__luabind_cast_graph");
73 lua_gettable(L, LUA_REGISTRYINDEX);
74 m_casts = static_cast<cast_graph*>(lua_touserdata(L, -1));
75 lua_pop(L, 1);
77 lua_pushstring(L, "__luabind_class_id_map");
78 lua_gettable(L, LUA_REGISTRYINDEX);
79 m_classes = static_cast<class_id_map*>(lua_touserdata(L, -1));
80 lua_pop(L, 1);
83 luabind::detail::class_rep::class_rep(lua_State* L, const char* name)
84 : m_type(typeid(null_type))
85 , m_name(name)
86 , m_class_type(lua_class)
87 , m_operator_cache(0)
89 lua_newtable(L);
90 handle(L, -1).swap(m_table);
91 lua_newtable(L);
92 handle(L, -1).swap(m_default_table);
93 lua_pop(L, 2);
95 class_registry* r = class_registry::get_registry(L);
96 assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()");
98 lua_rawgeti(L, LUA_REGISTRYINDEX, r->lua_class());
99 lua_setmetatable(L, -2);
100 lua_pushvalue(L, -1); // duplicate our user data
101 m_self_ref.set(L);
103 m_instance_metatable = r->lua_instance();
105 lua_pushstring(L, "__luabind_cast_graph");
106 lua_gettable(L, LUA_REGISTRYINDEX);
107 m_casts = static_cast<cast_graph*>(lua_touserdata(L, -1));
108 lua_pop(L, 1);
110 lua_pushstring(L, "__luabind_class_id_map");
111 lua_gettable(L, LUA_REGISTRYINDEX);
112 m_classes = static_cast<class_id_map*>(lua_touserdata(L, -1));
113 lua_pop(L, 1);
116 luabind::detail::class_rep::~class_rep()
120 // leaves object on lua stack
121 std::pair<void*,void*>
122 luabind::detail::class_rep::allocate(lua_State* L) const
124 const int size = sizeof(object_rep);
125 char* mem = static_cast<char*>(lua_newuserdata(L, size));
126 return std::pair<void*,void*>(mem, (void*)0);
129 namespace
132 bool super_deprecation_disabled = false;
134 } // namespace unnamed
136 // this is called as metamethod __call on the class_rep.
137 int luabind::detail::class_rep::constructor_dispatcher(lua_State* L)
139 class_rep* cls = static_cast<class_rep*>(lua_touserdata(L, 1));
141 int args = lua_gettop(L);
143 push_new_instance(L, cls);
145 if (super_deprecation_disabled
146 && cls->get_class_type() == class_rep::lua_class
147 && !cls->bases().empty())
149 lua_pushstring(L, "super");
150 lua_pushvalue(L, 1);
151 lua_pushvalue(L, -3);
152 lua_pushcclosure(L, super_callback, 2);
153 lua_settable(L, LUA_GLOBALSINDEX);
156 lua_pushvalue(L, -1);
157 lua_replace(L, 1);
159 cls->get_table(L);
160 lua_pushliteral(L, "__init");
161 lua_gettable(L, -2);
163 lua_insert(L, 1);
165 lua_pop(L, 1);
166 lua_insert(L, 1);
168 lua_call(L, args, 0);
170 if (super_deprecation_disabled)
172 lua_pushstring(L, "super");
173 lua_pushnil(L);
174 lua_settable(L, LUA_GLOBALSINDEX);
177 return 1;
180 void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo)
182 // If you hit this assert you are deriving from a type that is not registered
183 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
184 // Please note that if you don't need to have access to the base class or the
185 // conversion from the derived class to the base class, you don't need
186 // to tell luabind that it derives.
187 assert(binfo.base && "You cannot derive from an unregistered type");
189 class_rep* bcrep = binfo.base;
191 // import all static constants
192 for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin();
193 i != bcrep->m_static_constants.end(); ++i)
195 int& v = m_static_constants[i->first];
196 v = i->second;
199 // also, save the baseclass info to be used for typecasts
200 m_bases.push_back(binfo);
203 LUABIND_API void luabind::disable_super_deprecation()
205 super_deprecation_disabled = true;
208 int luabind::detail::class_rep::super_callback(lua_State* L)
210 int args = lua_gettop(L);
212 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
213 class_rep* base = crep->bases()[0].base;
215 if (base->bases().empty())
217 lua_pushstring(L, "super");
218 lua_pushnil(L);
219 lua_settable(L, LUA_GLOBALSINDEX);
221 else
223 lua_pushstring(L, "super");
224 lua_pushlightuserdata(L, base);
225 lua_pushvalue(L, lua_upvalueindex(2));
226 lua_pushcclosure(L, super_callback, 2);
227 lua_settable(L, LUA_GLOBALSINDEX);
230 base->get_table(L);
231 lua_pushstring(L, "__init");
232 lua_gettable(L, -2);
233 lua_insert(L, 1);
234 lua_pop(L, 1);
236 lua_pushvalue(L, lua_upvalueindex(2));
237 lua_insert(L, 2);
239 lua_call(L, args + 1, 0);
241 // TODO: instead of clearing the global variable "super"
242 // store it temporarily in the registry. maybe we should
243 // have some kind of warning if the super global is used?
244 lua_pushstring(L, "super");
245 lua_pushnil(L);
246 lua_settable(L, LUA_GLOBALSINDEX);
248 return 0;
253 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L)
255 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
257 // get first table
258 crep->get_table(L);
260 // copy key, value
261 lua_pushvalue(L, -3);
262 lua_pushvalue(L, -3);
263 lua_rawset(L, -3);
264 // pop table
265 lua_pop(L, 1);
267 // get default table
268 crep->get_default_table(L);
269 lua_replace(L, 1);
270 lua_rawset(L, -3);
272 crep->m_operator_cache = 0; // invalidate cache
274 return 0;
278 stack:
279 1: class_rep
280 2: member name
282 int luabind::detail::class_rep::static_class_gettable(lua_State* L)
284 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
286 // look in the static function table
287 crep->get_default_table(L);
288 lua_pushvalue(L, 2);
289 lua_gettable(L, -2);
290 if (!lua_isnil(L, -1)) return 1;
291 else lua_pop(L, 2);
293 const char* key = lua_tostring(L, 2);
295 if (std::strlen(key) != lua_strlen(L, 2))
297 lua_pushnil(L);
298 return 1;
301 std::map<const char*, int, ltstr>::const_iterator j = crep->m_static_constants.find(key);
303 if (j != crep->m_static_constants.end())
305 lua_pushnumber(L, j->second);
306 return 1;
309 #ifndef LUABIND_NO_ERROR_CHECKING
312 std::string msg = "no static '";
313 msg += key;
314 msg += "' in class '";
315 msg += crep->name();
316 msg += "'";
317 lua_pushstring(L, msg.c_str());
319 lua_error(L);
321 #endif
323 lua_pushnil(L);
325 return 1;
328 bool luabind::detail::is_class_rep(lua_State* L, int index)
330 if (lua_getmetatable(L, index) == 0) return false;
332 lua_pushstring(L, "__luabind_classrep");
333 lua_gettable(L, -2);
334 if (lua_toboolean(L, -1))
336 lua_pop(L, 2);
337 return true;
340 lua_pop(L, 2);
341 return false;
344 void luabind::detail::finalize(lua_State* L, class_rep* crep)
346 if (crep->get_class_type() != class_rep::lua_class) return;
348 // lua_pushvalue(L, -1); // copy the object ref
349 crep->get_table(L);
350 lua_pushliteral(L, "__finalize");
351 lua_gettable(L, -2);
352 lua_remove(L, -2);
354 if (lua_isnil(L, -1))
356 lua_pop(L, 1);
358 else
360 lua_pushvalue(L, -2);
361 lua_call(L, 1, 0);
364 for (std::vector<class_rep::base_info>::const_iterator
365 i = crep->bases().begin(); i != crep->bases().end(); ++i)
367 if (i->base) finalize(L, i->base);
371 void luabind::detail::class_rep::cache_operators(lua_State* L)
373 m_operator_cache = 0x1;
375 for (int i = 0; i < number_of_operators; ++i)
377 get_table(L);
378 lua_pushstring(L, get_operator_name(i));
379 lua_rawget(L, -2);
381 if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1);
383 lua_pop(L, 2);
387 bool luabind::detail::class_rep::has_operator_in_lua(lua_State* L, int id)
389 if ((m_operator_cache & 0x1) == 0)
390 cache_operators(L);
392 const int mask = 1 << (id + 1);
394 return (m_operator_cache & mask) != 0;