aboutsummaryrefslogtreecommitdiff
path: root/src/deep.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/deep.cpp')
-rw-r--r--src/deep.cpp87
1 files changed, 42 insertions, 45 deletions
diff --git a/src/deep.cpp b/src/deep.cpp
index a39e0f8..dfa3579 100644
--- a/src/deep.cpp
+++ b/src/deep.cpp
@@ -177,28 +177,29 @@ void DeepFactory::DeleteDeepObject(lua_State* L_, DeepPrelude* o_)
177 177
178/* 178/*
179 * Push a proxy userdata on the stack. 179 * Push a proxy userdata on the stack.
180 * returns nullptr if ok, else some error string related to bad factory behavior or module require problem 180 * raises an error in case of problem (error cannot happen with mode_ == LookupMode::ToKeeper)
181 * (error cannot happen with mode_ == LookupMode::ToKeeper)
182 * 181 *
183 * Initializes necessary structures if it's the first time 'factory' is being 182 * Initializes necessary structures if it's the first time 'factory' is being used in
184 * used in this Lua state (metatable, registring it). Otherwise, increments the 183 * this Lua state (metatable, registring it). Otherwise, increments the reference count.
185 * reference count.
186 */ 184 */
187std::string_view DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int nuv_, LookupMode mode_) 185void DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int nuv_, LookupMode mode_, lua_State* errL_)
188{ 186{
189 // Check if a proxy already exists 187 STACK_CHECK_START_REL(L_, 0);
190 kDeepProxyCacheRegKey.getSubTableMode(L_, "v"); // L_: DPC 188 kDeepProxyCacheRegKey.getSubTableMode(L_, "v"); // L_: DPC
189
190 // Check if a proxy already exists
191 lua_pushlightuserdata(L_, prelude_); // L_: DPC deep 191 lua_pushlightuserdata(L_, prelude_); // L_: DPC deep
192 lua_rawget(L_, -2); // L_: DPC proxy 192 lua_rawget(L_, -2); // L_: DPC proxy
193 if (!lua_isnil(L_, -1)) { 193 if (!lua_isnil(L_, -1)) {
194 lua_remove(L_, -2); // L_: proxy 194 lua_remove(L_, -2); // L_: proxy
195 return std::string_view{}; 195 STACK_CHECK(L_, 1);
196 return;
196 } else { 197 } else {
197 lua_pop(L_, 1); // L_: DPC 198 lua_pop(L_, 1); // L_: DPC
198 } 199 }
200 STACK_CHECK(L_, 1);
199 201
200 STACK_GROW(L_, 7); 202 STACK_GROW(L_, 7);
201 STACK_CHECK_START_REL(L_, 0);
202 203
203 // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) 204 // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4)
204 DeepPrelude** const _proxy{ lua_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // L_: DPC proxy 205 DeepPrelude** const _proxy{ lua_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // L_: DPC proxy
@@ -219,9 +220,7 @@ std::string_view DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_,
219 factory.createMetatable(L_); // L_: DPC proxy metatable 220 factory.createMetatable(L_); // L_: DPC proxy metatable
220 if (lua_gettop(L_) - _oldtop != 1 || !lua_istable(L_, -1)) { 221 if (lua_gettop(L_) - _oldtop != 1 || !lua_istable(L_, -1)) {
221 // factory didn't push exactly 1 value, or the value it pushed is not a table: ERROR! 222 // factory didn't push exactly 1 value, or the value it pushed is not a table: ERROR!
222 lua_settop(L_, _oldtop); // L_: DPC proxy X 223 raise_luaL_error(errL_, "Bad DeepFactory::createMetatable overload: unexpected pushed value");
223 lua_pop(L_, 3); // L_:
224 return "Bad DeepFactory::createMetatable overload: unexpected pushed value";
225 } 224 }
226 // if the metatable contains a __gc, we will call it from our own 225 // if the metatable contains a __gc, we will call it from our own
227 std::ignore = luaG_getfield(L_, -1, "__gc"); // L_: DPC proxy metatable __gc 226 std::ignore = luaG_getfield(L_, -1, "__gc"); // L_: DPC proxy metatable __gc
@@ -248,40 +247,42 @@ std::string_view DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_,
248 // L.registry._LOADED exists without having registered the 'package' library. 247 // L.registry._LOADED exists without having registered the 'package' library.
249 lua_getglobal(L_, "require"); // L_: DPC proxy metatable require() 248 lua_getglobal(L_, "require"); // L_: DPC proxy metatable require()
250 // check that the module is already loaded (or being loaded, we are happy either way) 249 // check that the module is already loaded (or being loaded, we are happy either way)
251 if (lua_isfunction(L_, -1)) { 250 if (!lua_isfunction(L_, -1)) { // a module name, but no require() function :-(
252 std::ignore = lua_pushstringview(L_, _modname); // L_: DPC proxy metatable require() "module" 251 raise_luaL_error(errL_, "lanes receiving deep userdata should register the 'package' library");
253 if (luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) == LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED 252 }
254 lua_pushvalue(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED "module" 253
255 lua_rawget(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED module 254 std::ignore = lua_pushstringview(L_, _modname); // L_: DPC proxy metatable require() "module"
256 int const _alreadyloaded{ lua_toboolean(L_, -1) }; 255 if (luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) != LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED
257 if (!_alreadyloaded) { // not loaded 256 // no L.registry._LOADED; can this ever happen?
258 lua_pop(L_, 2); // L_: DPC proxy metatable require() "module" 257 lua_pop(L_, 6); // L_:
259 // require "modname" 258 raise_luaL_error(errL_, "unexpected error while requiring a module identified by DeepFactory::moduleName");
260 LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error? 259 }
261 if (_require_result != LuaError::OK) { 260
262 // failed, return the error message 261 lua_pushvalue(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED "module"
263 lua_pushfstring(L_, "error while requiring '" STRINGVIEW_FMT "' identified by DeepFactory::moduleName: ", _modname.size(), _modname.data()); 262 lua_rawget(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED module
264 lua_insert(L_, -2); // L_: DPC proxy metatable prefix error 263 int const _alreadyloaded{ lua_toboolean(L_, -1) };
265 lua_concat(L_, 2); // L_: DPC proxy metatable error 264 if (!_alreadyloaded) { // not loaded
266 return lua_tostringview(L_, -1); 265 lua_pop(L_, 2); // L_: DPC proxy metatable require() "module"
267 } 266 // require "modname". in case of error, raise it in errL_
268 } else { // already loaded, we are happy 267 if (L_ == errL_) {
269 lua_pop(L_, 4); // L_: DPC proxy metatable 268 lua_call(L_, 1, 0); // L_: DPC proxy metatable module
269 } else {
270 LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error?
271 if (_require_result != LuaError::OK) {
272 // failed, raise the error in the proper state
273 std::ignore = lua_pushstringview(errL_, lua_tostringview(L_, -1));
274 raise_lua_error(errL_);
270 } 275 }
271 } else { // no L.registry._LOADED; can this ever happen?
272 lua_pop(L_, 6); // L_:
273 return std::string_view{ "unexpected error while requiring a module identified by DeepFactory::moduleName" };
274 } 276 }
275 } else { // a module name, but no require() function :-( 277 } else { // already loaded, we are happy
276 lua_pop(L_, 4); // L_: 278 lua_pop(L_, 4); // L_: DPC proxy metatable
277 return std::string_view{ "lanes receiving deep userdata should register the 'package' library" };
278 } 279 }
279 } 280 }
280 } 281 }
281 STACK_CHECK(L_, 2); // DPC proxy metatable 282 STACK_CHECK(L_, 3); // DPC proxy metatable
282 LUA_ASSERT(L_, lua_type_as_enum(L_, -2) == LuaType::USERDATA); 283 LUA_ASSERT(L_, lua_type_as_enum(L_, -2) == LuaType::USERDATA);
283 LUA_ASSERT(L_, lua_istable(L_, -1)); 284 LUA_ASSERT(L_, lua_istable(L_, -1));
284 lua_setmetatable(L_, -2); // DPC proxy 285 lua_setmetatable(L_, -2); // DPC proxy
285 286
286 // If we're here, we obviously had to create a new proxy, so cache it. 287 // If we're here, we obviously had to create a new proxy, so cache it.
287 lua_pushlightuserdata(L_, prelude_); // L_: DPC proxy deep 288 lua_pushlightuserdata(L_, prelude_); // L_: DPC proxy deep
@@ -289,8 +290,7 @@ std::string_view DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_,
289 lua_rawset(L_, -4); // L_: DPC proxy 290 lua_rawset(L_, -4); // L_: DPC proxy
290 lua_remove(L_, -2); // L_: proxy 291 lua_remove(L_, -2); // L_: proxy
291 LUA_ASSERT(L_, lua_type_as_enum(L_, -1) == LuaType::USERDATA); 292 LUA_ASSERT(L_, lua_type_as_enum(L_, -1) == LuaType::USERDATA);
292 STACK_CHECK(L_, 0); 293 STACK_CHECK(L_, 1);
293 return std::string_view{};
294} 294}
295 295
296// ################################################################################################# 296// #################################################################################################
@@ -335,10 +335,7 @@ int DeepFactory::pushDeepUserdata(DestState L_, int nuv_) const
335 raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack"); 335 raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack");
336 } 336 }
337 337
338 std::string_view const _err{ DeepFactory::PushDeepProxy(L_, _prelude, nuv_, LookupMode::LaneBody) }; // proxy 338 DeepFactory::PushDeepProxy(L_, _prelude, nuv_, LookupMode::LaneBody, L_); // proxy
339 if (!_err.empty()) {
340 raise_luaL_error(L_, _err.data());
341 }
342 STACK_CHECK(L_, 1); 339 STACK_CHECK(L_, 1);
343 return 1; 340 return 1;
344} 341}