docs: Fix spelling.
[luabind.git] / src / class_rep.cpp
blobb3b95ffea7937194cf791ac4cf386e3ed4c7f97b
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, 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 cls->get_table(L);
146 lua_setfenv(L, -2);
148 lua_rawgeti(L, LUA_REGISTRYINDEX, cls->metatable_ref());
149 lua_setmetatable(L, -2);
151 if (super_deprecation_disabled
152 && cls->get_class_type() == class_rep::lua_class
153 && !cls->bases().empty())
155 lua_pushstring(L, "super");
156 lua_pushvalue(L, 1);
157 lua_pushvalue(L, -3);
158 lua_pushcclosure(L, super_callback, 2);
159 lua_settable(L, LUA_GLOBALSINDEX);
162 lua_pushvalue(L, -1);
163 lua_replace(L, 1);
165 cls->get_table(L);
166 lua_pushliteral(L, "__init");
167 lua_gettable(L, -2);
169 lua_insert(L, 1);
171 lua_pop(L, 1);
172 lua_insert(L, 1);
174 lua_call(L, args, 0);
176 if (super_deprecation_disabled)
178 lua_pushstring(L, "super");
179 lua_pushnil(L);
180 lua_settable(L, LUA_GLOBALSINDEX);
183 return 1;
186 void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo)
188 // If you hit this assert you are deriving from a type that is not registered
189 // in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
190 // Please note that if you don't need to have access to the base class or the
191 // conversion from the derived class to the base class, you don't need
192 // to tell luabind that it derives.
193 assert(binfo.base && "You cannot derive from an unregistered type");
195 class_rep* bcrep = binfo.base;
197 // import all static constants
198 for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin();
199 i != bcrep->m_static_constants.end(); ++i)
201 int& v = m_static_constants[i->first];
202 v = i->second;
205 // also, save the baseclass info to be used for typecasts
206 m_bases.push_back(binfo);
209 LUABIND_API void luabind::disable_super_deprecation()
211 super_deprecation_disabled = true;
214 int luabind::detail::class_rep::super_callback(lua_State* L)
216 int args = lua_gettop(L);
218 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
219 class_rep* base = crep->bases()[0].base;
221 if (base->bases().empty())
223 lua_pushstring(L, "super");
224 lua_pushnil(L);
225 lua_settable(L, LUA_GLOBALSINDEX);
227 else
229 lua_pushstring(L, "super");
230 lua_pushlightuserdata(L, base);
231 lua_pushvalue(L, lua_upvalueindex(2));
232 lua_pushcclosure(L, super_callback, 2);
233 lua_settable(L, LUA_GLOBALSINDEX);
236 base->get_table(L);
237 lua_pushstring(L, "__init");
238 lua_gettable(L, -2);
239 lua_insert(L, 1);
240 lua_pop(L, 1);
242 lua_pushvalue(L, lua_upvalueindex(2));
243 lua_insert(L, 2);
245 lua_call(L, args + 1, 0);
247 // TODO: instead of clearing the global variable "super"
248 // store it temporarily in the registry. maybe we should
249 // have some kind of warning if the super global is used?
250 lua_pushstring(L, "super");
251 lua_pushnil(L);
252 lua_settable(L, LUA_GLOBALSINDEX);
254 return 0;
259 int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L)
261 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
263 // get first table
264 crep->get_table(L);
266 // copy key, value
267 lua_pushvalue(L, -3);
268 lua_pushvalue(L, -3);
269 lua_rawset(L, -3);
270 // pop table
271 lua_pop(L, 1);
273 // get default table
274 crep->get_default_table(L);
275 lua_replace(L, 1);
276 lua_rawset(L, -3);
278 crep->m_operator_cache = 0; // invalidate cache
280 return 0;
284 stack:
285 1: class_rep
286 2: member name
288 int luabind::detail::class_rep::static_class_gettable(lua_State* L)
290 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, 1));
292 // look in the static function table
293 crep->get_default_table(L);
294 lua_pushvalue(L, 2);
295 lua_gettable(L, -2);
296 if (!lua_isnil(L, -1)) return 1;
297 else lua_pop(L, 2);
299 const char* key = lua_tostring(L, 2);
301 if (std::strlen(key) != lua_strlen(L, 2))
303 lua_pushnil(L);
304 return 1;
307 std::map<const char*, int, ltstr>::const_iterator j = crep->m_static_constants.find(key);
309 if (j != crep->m_static_constants.end())
311 lua_pushnumber(L, j->second);
312 return 1;
315 #ifndef LUABIND_NO_ERROR_CHECKING
318 std::string msg = "no static '";
319 msg += key;
320 msg += "' in class '";
321 msg += crep->name();
322 msg += "'";
323 lua_pushstring(L, msg.c_str());
325 lua_error(L);
327 #endif
329 lua_pushnil(L);
331 return 1;
334 bool luabind::detail::is_class_rep(lua_State* L, int index)
336 if (lua_getmetatable(L, index) == 0) return false;
338 lua_pushstring(L, "__luabind_classrep");
339 lua_gettable(L, -2);
340 if (lua_toboolean(L, -1))
342 lua_pop(L, 2);
343 return true;
346 lua_pop(L, 2);
347 return false;
350 void luabind::detail::finalize(lua_State* L, class_rep* crep)
352 if (crep->get_class_type() != class_rep::lua_class) return;
354 // lua_pushvalue(L, -1); // copy the object ref
355 crep->get_table(L);
356 lua_pushliteral(L, "__finalize");
357 lua_gettable(L, -2);
358 lua_remove(L, -2);
360 if (lua_isnil(L, -1))
362 lua_pop(L, 1);
364 else
366 lua_pushvalue(L, -2);
367 lua_call(L, 1, 0);
370 for (std::vector<class_rep::base_info>::const_iterator
371 i = crep->bases().begin(); i != crep->bases().end(); ++i)
373 if (i->base) finalize(L, i->base);
377 void luabind::detail::class_rep::cache_operators(lua_State* L)
379 m_operator_cache = 0x1;
381 for (int i = 0; i < number_of_operators; ++i)
383 get_table(L);
384 lua_pushstring(L, get_operator_name(i));
385 lua_rawget(L, -2);
387 if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1);
389 lua_pop(L, 2);
393 bool luabind::detail::class_rep::has_operator_in_lua(lua_State* L, int id)
395 if ((m_operator_cache & 0x1) == 0)
396 cache_operators(L);
398 const int mask = 1 << (id + 1);
400 return (m_operator_cache & mask) != 0;