aboutsummaryrefslogtreecommitdiff
path: root/src/state.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/state.cpp')
-rw-r--r--src/state.cpp327
1 files changed, 147 insertions, 180 deletions
diff --git a/src/state.cpp b/src/state.cpp
index e71865d..ebb24dd 100644
--- a/src/state.cpp
+++ b/src/state.cpp
@@ -40,7 +40,7 @@ THE SOFTWARE.
40// ################################################################################################# 40// #################################################################################################
41 41
42/*---=== Serialize require ===--- 42/*---=== Serialize require ===---
43*/ 43 */
44 44
45//--- 45//---
46// [val,...]= new_require( ... ) 46// [val,...]= new_require( ... )
@@ -52,55 +52,51 @@ THE SOFTWARE.
52[[nodiscard]] static int luaG_new_require(lua_State* L_) 52[[nodiscard]] static int luaG_new_require(lua_State* L_)
53{ 53{
54 int rc; 54 int rc;
55 int const args = lua_gettop(L_); // args 55 int const args = lua_gettop(L_); // L_: args
56 Universe* U = universe_get(L_); 56 Universe* U = universe_get(L_);
57 //char const* modname = luaL_checkstring(L_, 1); 57 // char const* modname = luaL_checkstring(L_, 1);
58 58
59 STACK_GROW(L_, 1); 59 STACK_GROW(L_, 1);
60 60
61 lua_pushvalue(L_, lua_upvalueindex( 1)); // args require 61 lua_pushvalue(L_, lua_upvalueindex(1)); // L_: args require
62 lua_insert(L_, 1); // require args 62 lua_insert(L_, 1); // L_: require args
63 63
64 // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would 64 // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would
65 // leave us locked, blocking any future 'require' calls from other lanes. 65 // leave us locked, blocking any future 'require' calls from other lanes.
66 66
67 U->require_cs.lock(); 67 U->require_cs.lock();
68 // starting with Lua 5.4, require may return a second optional value, so we need LUA_MULTRET 68 // starting with Lua 5.4, require may return a second optional value, so we need LUA_MULTRET
69 rc = lua_pcall(L_, args, LUA_MULTRET, 0 /*errfunc*/ ); // err|result(s) 69 rc = lua_pcall(L_, args, LUA_MULTRET, 0 /*errfunc*/); // L_: err|result(s)
70 U->require_cs.unlock(); 70 U->require_cs.unlock();
71 71
72 // the required module (or an error message) is left on the stack as returned value by original require function 72 // the required module (or an error message) is left on the stack as returned value by original require function
73 73
74 if (rc != LUA_OK) // LUA_ERRRUN / LUA_ERRMEM ? 74 if (rc != LUA_OK) { // LUA_ERRRUN / LUA_ERRMEM ?
75 {
76 raise_lua_error(L_); 75 raise_lua_error(L_);
77 } 76 }
78 // should be 1 for Lua <= 5.3, 1 or 2 starting with Lua 5.4 77 // should be 1 for Lua <= 5.3, 1 or 2 starting with Lua 5.4
79 return lua_gettop(L_); // result(s) 78 return lua_gettop(L_); // L_: result(s)
80} 79}
81 80
82// ################################################################################################# 81// #################################################################################################
83 82
84/* 83/*
85* Serialize calls to 'require', if it exists 84 * Serialize calls to 'require', if it exists
86*/ 85 */
87void serialize_require(DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L_) 86void serialize_require(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_)
88{ 87{
89 STACK_GROW(L_, 1); 88 STACK_GROW(L_, 1);
90 STACK_CHECK_START_REL(L_, 0); 89 STACK_CHECK_START_REL(L_, 0);
91 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "serializing require()\n" INDENT_END)); 90 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "serializing require()\n" INDENT_END(U_)));
92 91
93 // Check 'require' is there and not already wrapped; if not, do nothing 92 // Check 'require' is there and not already wrapped; if not, do nothing
94 // 93 //
95 lua_getglobal(L_, "require"); 94 lua_getglobal(L_, "require");
96 if (lua_isfunction(L_, -1) && lua_tocfunction(L_, -1) != luaG_new_require) 95 if (lua_isfunction(L_, -1) && lua_tocfunction(L_, -1) != luaG_new_require) {
97 {
98 // [-1]: original 'require' function 96 // [-1]: original 'require' function
99 lua_pushcclosure(L_, luaG_new_require, 1 /*upvalues*/); 97 lua_pushcclosure(L_, luaG_new_require, 1 /*upvalues*/);
100 lua_setglobal(L_, "require"); 98 lua_setglobal(L_, "require");
101 } 99 } else {
102 else
103 {
104 // [-1]: nil 100 // [-1]: nil
105 lua_pop(L_, 1); 101 lua_pop(L_, 1);
106 } 102 }
@@ -115,72 +111,67 @@ void serialize_require(DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L_)
115[[nodiscard]] static int require_lanes_core(lua_State* L_) 111[[nodiscard]] static int require_lanes_core(lua_State* L_)
116{ 112{
117 // leaves a copy of 'lanes.core' module table on the stack 113 // leaves a copy of 'lanes.core' module table on the stack
118 luaL_requiref( L_, "lanes.core", luaopen_lanes_core, 0); 114 luaL_requiref(L_, "lanes.core", luaopen_lanes_core, 0);
119 return 1; 115 return 1;
120} 116}
121 117
122// ################################################################################################# 118// #################################################################################################
123 119
124static luaL_Reg const libs[] = 120static luaL_Reg const libs[] = {
125{ 121 { LUA_LOADLIBNAME, luaopen_package },
126 { LUA_LOADLIBNAME, luaopen_package}, 122 { LUA_TABLIBNAME, luaopen_table },
127 { LUA_TABLIBNAME, luaopen_table}, 123 { LUA_STRLIBNAME, luaopen_string },
128 { LUA_STRLIBNAME, luaopen_string}, 124 { LUA_MATHLIBNAME, luaopen_math },
129 { LUA_MATHLIBNAME, luaopen_math},
130#ifndef PLATFORM_XBOX // no os/io libs on xbox 125#ifndef PLATFORM_XBOX // no os/io libs on xbox
131 { LUA_OSLIBNAME, luaopen_os}, 126 { LUA_OSLIBNAME, luaopen_os },
132 { LUA_IOLIBNAME, luaopen_io}, 127 { LUA_IOLIBNAME, luaopen_io },
133#endif // PLATFORM_XBOX 128#endif // PLATFORM_XBOX
134#if LUA_VERSION_NUM >= 503 129#if LUA_VERSION_NUM >= 503
135 { LUA_UTF8LIBNAME, luaopen_utf8}, 130 { LUA_UTF8LIBNAME, luaopen_utf8 },
136#endif 131#endif
137#if LUA_VERSION_NUM >= 502 132#if LUA_VERSION_NUM >= 502
138#ifdef luaopen_bit32 133#ifdef luaopen_bit32
139 { LUA_BITLIBNAME, luaopen_bit32}, 134 { LUA_BITLIBNAME, luaopen_bit32 },
140#endif 135#endif
141 { LUA_COLIBNAME, luaopen_coroutine}, // Lua 5.2: coroutine is no longer a part of base! 136 { LUA_COLIBNAME, luaopen_coroutine }, // Lua 5.2: coroutine is no longer a part of base!
142#else // LUA_VERSION_NUM 137#else // LUA_VERSION_NUM
143 { LUA_COLIBNAME, nullptr }, // Lua 5.1: part of base package 138 { LUA_COLIBNAME, nullptr }, // Lua 5.1: part of base package
144#endif // LUA_VERSION_NUM 139#endif // LUA_VERSION_NUM
145 { LUA_DBLIBNAME, luaopen_debug}, 140 { LUA_DBLIBNAME, luaopen_debug },
146#if LUAJIT_FLAVOR() != 0 // building against LuaJIT headers, add some LuaJIT-specific libs 141#if LUAJIT_FLAVOR() != 0 // building against LuaJIT headers, add some LuaJIT-specific libs
147//#pragma message( "supporting JIT base libs") 142 // #pragma message( "supporting JIT base libs")
148 { LUA_BITLIBNAME, luaopen_bit}, 143 { LUA_BITLIBNAME, luaopen_bit },
149 { LUA_JITLIBNAME, luaopen_jit}, 144 { LUA_JITLIBNAME, luaopen_jit },
150 { LUA_FFILIBNAME, luaopen_ffi}, 145 { LUA_FFILIBNAME, luaopen_ffi },
151#endif // LUAJIT_FLAVOR() 146#endif // LUAJIT_FLAVOR()
152 147
153 { LUA_DBLIBNAME, luaopen_debug}, 148 { LUA_DBLIBNAME, luaopen_debug },
154 { "lanes.core", require_lanes_core}, // So that we can open it like any base library (possible since we have access to the init function) 149 { "lanes.core", require_lanes_core }, // So that we can open it like any base library (possible since we have access to the init function)
155 // 150 //
156 { "base", nullptr }, // ignore "base" (already acquired it) 151 { "base", nullptr }, // ignore "base" (already acquired it)
157 { nullptr, nullptr } 152 { nullptr, nullptr }
158}; 153};
159 154
160// ################################################################################################# 155// #################################################################################################
161 156
162static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L_, char const* name_, size_t len_) 157static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L_, char const* name_, size_t len_)
163{ 158{
164 for (int i{ 0 }; libs[i].name; ++i) 159 for (int i{ 0 }; libs[i].name; ++i) {
165 { 160 if (strncmp(name_, libs[i].name, len_) == 0) {
166 if (strncmp( name_, libs[i].name, len_) == 0)
167 {
168 lua_CFunction libfunc = libs[i].func; 161 lua_CFunction libfunc = libs[i].func;
169 name_ = libs[i].name; // note that the provided name_ doesn't necessarily ends with '\0', hence len_ 162 name_ = libs[i].name; // note that the provided name_ doesn't necessarily ends with '\0', hence len_
170 if (libfunc != nullptr) 163 if (libfunc != nullptr) {
171 {
172 bool const isLanesCore{ libfunc == require_lanes_core }; // don't want to create a global for "lanes.core" 164 bool const isLanesCore{ libfunc == require_lanes_core }; // don't want to create a global for "lanes.core"
173 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END, (int) len_, name_)); 165 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END(U_), (int) len_, name_));
174 STACK_CHECK_START_REL(L_, 0); 166 STACK_CHECK_START_REL(L_, 0);
175 // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) 167 // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack)
176 luaL_requiref( L_, name_, libfunc, !isLanesCore); 168 luaL_requiref(L_, name_, libfunc, !isLanesCore);
177 // lanes.core doesn't declare a global, so scan it here and now 169 // lanes.core doesn't declare a global, so scan it here and now
178 if (isLanesCore == true) 170 if (isLanesCore == true) {
179 { 171 populate_func_lookup_table(L_, -1, name_);
180 populate_func_lookup_table( L_, -1, name_);
181 } 172 }
182 lua_pop( L_, 1); 173 lua_pop(L_, 1);
183 STACK_CHECK( L_, 0); 174 STACK_CHECK(L_, 0);
184 } 175 }
185 break; 176 break;
186 } 177 }
@@ -190,90 +181,80 @@ static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L_, char cons
190// ################################################################################################# 181// #################################################################################################
191 182
192// just like lua_xmove, args are (from, to) 183// just like lua_xmove, args are (from, to)
193static void copy_one_time_settings(Universe* U, SourceState L1, DestState L2) 184static void copy_one_time_settings(Universe* U_, SourceState L1_, DestState L2_)
194{ 185{
195 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); 186 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U_ });
196 187
197 STACK_GROW(L1, 2); 188 STACK_GROW(L1_, 2);
198 STACK_CHECK_START_REL(L1, 0); 189 STACK_CHECK_START_REL(L1_, 0);
199 STACK_CHECK_START_REL(L2, 0); 190 STACK_CHECK_START_REL(L2_, 0);
200 191
201 DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END)); 192 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END(U_)));
202 193
203 kConfigRegKey.pushValue(L1); // config 194 kConfigRegKey.pushValue(L1_); // L1_: config
204 // copy settings from from source to destination registry 195 // copy settings from from source to destination registry
205 InterCopyContext c{ U, L2, L1, {}, {}, {}, {}, {} }; 196 InterCopyContext c{ U_, L2_, L1_, {}, {}, {}, {}, {} };
206 if (c.inter_move(1) != InterCopyResult::Success) // // config 197 if (c.inter_move(1) != InterCopyResult::Success) { // L1_: L2_: config
207 { 198 raise_luaL_error(L1_, "failed to copy settings when loading lanes.core");
208 raise_luaL_error(L1, "failed to copy settings when loading lanes.core");
209 } 199 }
210 // set L2:_R[kConfigRegKey] = settings 200 // set L2:_R[kConfigRegKey] = settings
211 kConfigRegKey.setValue(L2, [](lua_State* L_) { lua_insert(L_, -2); }); // config 201 kConfigRegKey.setValue(L2_, [](lua_State* L_) { lua_insert(L_, -2); }); // L1_: L2_: config
212 STACK_CHECK(L2, 0); 202 STACK_CHECK(L2_, 0);
213 STACK_CHECK(L1, 0); 203 STACK_CHECK(L1_, 0);
214} 204}
215 205
216// ################################################################################################# 206// #################################################################################################
217 207
218void initialize_on_state_create( Universe* U, lua_State* L_) 208void initialize_on_state_create(Universe* U_, lua_State* L_)
219{ 209{
220 STACK_CHECK_START_REL(L_, 1); // settings 210 STACK_CHECK_START_REL(L_, 1); // L_: settings
221 lua_getfield(L_, -1, "on_state_create"); // settings on_state_create|nil 211 lua_getfield(L_, -1, "on_state_create"); // L_: settings on_state_create|nil
222 if (!lua_isnil(L_, -1)) 212 if (!lua_isnil(L_, -1)) {
223 {
224 // store C function pointer in an internal variable 213 // store C function pointer in an internal variable
225 U->on_state_create_func = lua_tocfunction(L_, -1); // settings on_state_create 214 U_->on_state_create_func = lua_tocfunction(L_, -1); // L_: settings on_state_create
226 if (U->on_state_create_func != nullptr) 215 if (U_->on_state_create_func != nullptr) {
227 {
228 // make sure the function doesn't have upvalues 216 // make sure the function doesn't have upvalues
229 char const* upname = lua_getupvalue(L_, -1, 1); // settings on_state_create upval? 217 char const* upname = lua_getupvalue(L_, -1, 1); // L_: settings on_state_create upval?
230 if (upname != nullptr) // should be "" for C functions with upvalues if any 218 if (upname != nullptr) { // should be "" for C functions with upvalues if any
231 {
232 raise_luaL_error(L_, "on_state_create shouldn't have upvalues"); 219 raise_luaL_error(L_, "on_state_create shouldn't have upvalues");
233 } 220 }
234 // remove this C function from the config table so that it doesn't cause problems 221 // remove this C function from the config table so that it doesn't cause problems
235 // when we transfer the config table in newly created Lua states 222 // when we transfer the config table in newly created Lua states
236 lua_pushnil(L_); // settings on_state_create nil 223 lua_pushnil(L_); // L_: settings on_state_create nil
237 lua_setfield(L_, -3, "on_state_create"); // settings on_state_create 224 lua_setfield(L_, -3, "on_state_create"); // L_: settings on_state_create
238 } 225 } else {
239 else
240 {
241 // optim: store marker saying we have such a function in the config table 226 // optim: store marker saying we have such a function in the config table
242 U->on_state_create_func = (lua_CFunction) initialize_on_state_create; 227 U_->on_state_create_func = (lua_CFunction) initialize_on_state_create;
243 } 228 }
244 } 229 }
245 lua_pop(L_, 1); // settings 230 lua_pop(L_, 1); // L_: settings
246 STACK_CHECK(L_, 1); 231 STACK_CHECK(L_, 1);
247} 232}
248 233
249// ################################################################################################# 234// #################################################################################################
250 235
251lua_State* create_state(Universe* U, lua_State* from_) 236lua_State* create_state(Universe* U_, lua_State* from_)
252{ 237{
253 lua_State* L; 238 lua_State* L;
254#if LUAJIT_FLAVOR() == 64 239#if LUAJIT_FLAVOR() == 64
255 // for some reason, LuaJIT 64 bits does not support creating a state with lua_newstate... 240 // for some reason, LuaJIT 64 bits does not support creating a state with lua_newstate...
256 L = luaL_newstate(); 241 L = luaL_newstate();
257#else // LUAJIT_FLAVOR() == 64 242#else // LUAJIT_FLAVOR() == 64
258 if (U->provide_allocator != nullptr) // we have a function we can call to obtain an allocator 243 if (U_->provide_allocator != nullptr) { // we have a function we can call to obtain an allocator
259 { 244 lua_pushcclosure(from_, U_->provide_allocator, 0);
260 lua_pushcclosure( from_, U->provide_allocator, 0); 245 lua_call(from_, 0, 1);
261 lua_call( from_, 0, 1);
262 { 246 {
263 AllocatorDefinition* const def{ lua_tofulluserdata<AllocatorDefinition>(from_, -1) }; 247 AllocatorDefinition* const def{ lua_tofulluserdata<AllocatorDefinition>(from_, -1) };
264 L = lua_newstate( def->m_allocF, def->m_allocUD); 248 L = lua_newstate(def->m_allocF, def->m_allocUD);
265 } 249 }
266 lua_pop( from_, 1); 250 lua_pop(from_, 1);
267 } 251 } else {
268 else
269 {
270 // reuse the allocator provided when the master state was created 252 // reuse the allocator provided when the master state was created
271 L = lua_newstate(U->protected_allocator.m_allocF, U->protected_allocator.m_allocUD); 253 L = lua_newstate(U_->protected_allocator.m_allocF, U_->protected_allocator.m_allocUD);
272 } 254 }
273#endif // LUAJIT_FLAVOR() == 64 255#endif // LUAJIT_FLAVOR() == 64
274 256
275 if (L == nullptr) 257 if (L == nullptr) {
276 {
277 raise_luaL_error(from_, "luaG_newstate() failed while creating state; out of memory"); 258 raise_luaL_error(from_, "luaG_newstate() failed while creating state; out of memory");
278 } 259 }
279 return L; 260 return L;
@@ -281,35 +262,29 @@ lua_State* create_state(Universe* U, lua_State* from_)
281 262
282// ################################################################################################# 263// #################################################################################################
283 264
284void call_on_state_create(Universe* U, lua_State* L_, lua_State* from_, LookupMode mode_) 265void call_on_state_create(Universe* U_, lua_State* L_, lua_State* from_, LookupMode mode_)
285{ 266{
286 if (U->on_state_create_func != nullptr) 267 if (U_->on_state_create_func != nullptr) {
287 {
288 STACK_CHECK_START_REL(L_, 0); 268 STACK_CHECK_START_REL(L_, 0);
289 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); 269 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END(U_)));
290 if (U->on_state_create_func != (lua_CFunction) initialize_on_state_create) 270 if (U_->on_state_create_func != (lua_CFunction) initialize_on_state_create) {
291 {
292 // C function: recreate a closure in the new state, bypassing the lookup scheme 271 // C function: recreate a closure in the new state, bypassing the lookup scheme
293 lua_pushcfunction(L_, U->on_state_create_func); // on_state_create() 272 lua_pushcfunction(L_, U_->on_state_create_func); // on_state_create()
294 } 273 } else { // Lua function located in the config table, copied when we opened "lanes.core"
295 else // Lua function located in the config table, copied when we opened "lanes.core" 274 if (mode_ != LookupMode::LaneBody) {
296 {
297 if (mode_ != LookupMode::LaneBody)
298 {
299 // if attempting to call in a keeper state, do nothing because the function doesn't exist there 275 // if attempting to call in a keeper state, do nothing because the function doesn't exist there
300 // this doesn't count as an error though 276 // this doesn't count as an error though
301 STACK_CHECK(L_, 0); 277 STACK_CHECK(L_, 0);
302 return; 278 return;
303 } 279 }
304 kConfigRegKey.pushValue(L_); // {} 280 kConfigRegKey.pushValue(L_); // L_: {}
305 STACK_CHECK(L_, 1); 281 STACK_CHECK(L_, 1);
306 lua_getfield(L_, -1, "on_state_create"); // {} on_state_create() 282 lua_getfield(L_, -1, "on_state_create"); // L_: {} on_state_create()
307 lua_remove(L_, -2); // on_state_create() 283 lua_remove(L_, -2); // L_: on_state_create()
308 } 284 }
309 STACK_CHECK(L_, 1); 285 STACK_CHECK(L_, 1);
310 // capture error and raise it in caller state 286 // capture error and raise it in caller state
311 if (lua_pcall(L_, 0, 0, 0) != LUA_OK) 287 if (lua_pcall(L_, 0, 0, 0) != LUA_OK) {
312 {
313 raise_luaL_error(from_, "on_state_create failed: \"%s\"", lua_isstring(L_, -1) ? lua_tostring(L_, -1) : lua_typename(L_, lua_type(L_, -1))); 288 raise_luaL_error(from_, "on_state_create failed: \"%s\"", lua_isstring(L_, -1) ? lua_tostring(L_, -1) : lua_typename(L_, lua_type(L_, -1)));
314 } 289 }
315 STACK_CHECK(L_, 0); 290 STACK_CHECK(L_, 0);
@@ -319,28 +294,28 @@ void call_on_state_create(Universe* U, lua_State* L_, lua_State* from_, LookupMo
319// ################################################################################################# 294// #################################################################################################
320 295
321/* 296/*
322* Like 'luaL_openlibs()' but allows the set of libraries be selected 297 * Like 'luaL_openlibs()' but allows the set of libraries be selected
323* 298 *
324* nullptr no libraries, not even base 299 * nullptr no libraries, not even base
325* "" base library only 300 * "" base library only
326* "io,string" named libraries 301 * "io,string" named libraries
327* "*" all libraries 302 * "*" all libraries
328* 303 *
329* Base ("unpack", "print" etc.) is always added, unless 'libs' is nullptr. 304 * Base ("unpack", "print" etc.) is always added, unless 'libs' is nullptr.
330* 305 *
331* *NOT* called for keeper states! 306 * *NOT* called for keeper states!
332* 307 *
333*/ 308 */
334lua_State* luaG_newstate(Universe* U, SourceState from_, char const* libs_) 309lua_State* luaG_newstate(Universe* U_, SourceState from_, char const* libs_)
335{ 310{
336 DestState const L{ create_state(U, from_) }; 311 DestState const L{ create_state(U_, from_) };
337 312
338 STACK_GROW(L, 2); 313 STACK_GROW(L, 2);
339 STACK_CHECK_START_ABS(L, 0); 314 STACK_CHECK_START_ABS(L, 0);
340 315
341 // copy the universe as a light userdata (only the master state holds the full userdata) 316 // copy the universe as a light userdata (only the master state holds the full userdata)
342 // that way, if Lanes is required in this new state, we'll know we are part of this universe 317 // that way, if Lanes is required in this new state, we'll know we are part of this universe
343 universe_store( L, U); 318 universe_store(L, U_);
344 STACK_CHECK(L, 0); 319 STACK_CHECK(L, 0);
345 320
346 // we'll need this every time we transfer some C function from/to this state 321 // we'll need this every time we transfer some C function from/to this state
@@ -348,76 +323,68 @@ lua_State* luaG_newstate(Universe* U, SourceState from_, char const* libs_)
348 STACK_CHECK(L, 0); 323 STACK_CHECK(L, 0);
349 324
350 // neither libs (not even 'base') nor special init func: we are done 325 // neither libs (not even 'base') nor special init func: we are done
351 if (libs_ == nullptr && U->on_state_create_func == nullptr) 326 if (libs_ == nullptr && U_->on_state_create_func == nullptr) {
352 { 327 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_newstate(nullptr)\n" INDENT_END(U_)));
353 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate(nullptr)\n" INDENT_END));
354 return L; 328 return L;
355 } 329 }
356 330
357 DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); 331 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END(U_)));
358 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); 332 DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U_ });
359 333
360 // copy settings (for example because it may contain a Lua on_state_create function) 334 // copy settings (for example because it may contain a Lua on_state_create function)
361 copy_one_time_settings( U, from_, L); 335 copy_one_time_settings(U_, from_, L);
362 336
363 // 'lua.c' stops GC during initialization so perhaps its a good idea. :) 337 // 'lua.c' stops GC during initialization so perhaps its a good idea. :)
364 lua_gc(L, LUA_GCSTOP, 0); 338 lua_gc(L, LUA_GCSTOP, 0);
365 339
366
367 // Anything causes 'base' to be taken in 340 // Anything causes 'base' to be taken in
368 // 341 //
369 if (libs_ != nullptr) 342 if (libs_ != nullptr) {
370 {
371 // special "*" case (mainly to help with LuaJIT compatibility) 343 // special "*" case (mainly to help with LuaJIT compatibility)
372 // as we are called from luaopen_lanes_core() already, and that would deadlock 344 // as we are called from luaopen_lanes_core() already, and that would deadlock
373 if (libs_[0] == '*' && libs_[1] == 0) 345 if (libs_[0] == '*' && libs_[1] == 0) {
374 { 346 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END(U_)));
375 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); 347 luaL_openlibs(L);
376 luaL_openlibs( L);
377 // don't forget lanes.core for regular lane states 348 // don't forget lanes.core for regular lane states
378 open1lib( DEBUGSPEW_PARAM_COMMA( U) L, "lanes.core", 10); 349 open1lib(DEBUGSPEW_PARAM_COMMA(U_) L, "lanes.core", 10);
379 libs_ = nullptr; // done with libs 350 libs_ = nullptr; // done with libs
380 } 351 } else {
381 else 352 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "opening base library\n" INDENT_END(U_)));
382 {
383 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening base library\n" INDENT_END));
384#if LUA_VERSION_NUM >= 502 353#if LUA_VERSION_NUM >= 502
385 // open base library the same way as in luaL_openlibs() 354 // open base library the same way as in luaL_openlibs()
386 luaL_requiref( L, "_G", luaopen_base, 1); 355 luaL_requiref(L, "_G", luaopen_base, 1);
387 lua_pop( L, 1); 356 lua_pop(L, 1);
388#else // LUA_VERSION_NUM 357#else // LUA_VERSION_NUM
389 lua_pushcfunction( L, luaopen_base); 358 lua_pushcfunction(L, luaopen_base);
390 lua_pushstring( L, ""); 359 lua_pushstring(L, "");
391 lua_call( L, 1, 0); 360 lua_call(L, 1, 0);
392#endif // LUA_VERSION_NUM 361#endif // LUA_VERSION_NUM
393 } 362 }
394 } 363 }
395 STACK_CHECK(L, 0); 364 STACK_CHECK(L, 0);
396 365
397 // scan all libraries, open them one by one 366 // scan all libraries, open them one by one
398 if (libs_) 367 if (libs_) {
399 {
400 unsigned int len{ 0 }; 368 unsigned int len{ 0 };
401 for (char const* p{ libs_ }; *p; p += len) 369 for (char const* p{ libs_ }; *p; p += len) {
402 {
403 // skip delimiters ('.' can be part of name for "lanes.core") 370 // skip delimiters ('.' can be part of name for "lanes.core")
404 while( *p && !isalnum(*p) && *p != '.') 371 while (*p && !isalnum(*p) && *p != '.')
405 ++ p; 372 ++p;
406 // skip name 373 // skip name
407 len = 0; 374 len = 0;
408 while( isalnum(p[len]) || p[len] == '.') 375 while (isalnum(p[len]) || p[len] == '.')
409 ++ len; 376 ++len;
410 // open library 377 // open library
411 open1lib(DEBUGSPEW_PARAM_COMMA( U) L, p, len); 378 open1lib(DEBUGSPEW_PARAM_COMMA(U_) L, p, len);
412 } 379 }
413 } 380 }
414 lua_gc(L, LUA_GCRESTART, 0); 381 lua_gc(L, LUA_GCRESTART, 0);
415 382
416 serialize_require(DEBUGSPEW_PARAM_COMMA( U) L); 383 serialize_require(DEBUGSPEW_PARAM_COMMA(U_) L);
417 384
418 // call this after the base libraries are loaded and GC is restarted 385 // call this after the base libraries are loaded and GC is restarted
419 // will raise an error in from_ in case of problem 386 // will raise an error in from_ in case of problem
420 call_on_state_create(U, L, from_, LookupMode::LaneBody); 387 call_on_state_create(U_, L, from_, LookupMode::LaneBody);
421 388
422 STACK_CHECK(L, 0); 389 STACK_CHECK(L, 0);
423 // after all this, register everything we find in our name<->function database 390 // after all this, register everything we find in our name<->function database
@@ -427,18 +394,18 @@ lua_State* luaG_newstate(Universe* U, SourceState from_, char const* libs_)
427 394
428#if 1 && USE_DEBUG_SPEW() 395#if 1 && USE_DEBUG_SPEW()
429 // dump the lookup database contents 396 // dump the lookup database contents
430 kLookupRegKey.pushValue(L); // {} 397 kLookupRegKey.pushValue(L); // L: {}
431 lua_pushnil(L); // {} nil 398 lua_pushnil(L); // L: {} nil
432 while (lua_next(L, -2)) // {} k v 399 while (lua_next(L, -2)) { // L: {} k v
433 { 400 lua_getglobal(L, "print"); // L: {} k v print
434 lua_getglobal(L, "print"); // {} k v print 401 int const indent{ U_->debugspew_indent_depth.load(std::memory_order_relaxed) };
435 lua_pushlstring(L, DebugSpewIndentScope::debugspew_indent, U->debugspew_indent_depth.load(std::memory_order_relaxed)); // {} k v print " " 402 lua_pushlstring(L, DebugSpewIndentScope::debugspew_indent, indent); // L: {} k v print " "
436 lua_pushvalue(L, -4); // {} k v print " " k 403 lua_pushvalue(L, -4); // L: {} k v print " " k
437 lua_pushvalue(L, -4); // {} k v print " " k v 404 lua_pushvalue(L, -4); // L: {} k v print " " k v
438 lua_call(L, 3, 0); // {} k v 405 lua_call(L, 3, 0); // L: {} k v
439 lua_pop(L, 1); // {} k 406 lua_pop(L, 1); // L: {} k
440 } 407 }
441 lua_pop(L, 1); // {} 408 lua_pop(L, 1); // L: {}
442#endif // USE_DEBUG_SPEW() 409#endif // USE_DEBUG_SPEW()
443 410
444 lua_pop(L, 1); 411 lua_pop(L, 1);