aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lanes.c1
-rw-r--r--src/lanes.lua1
-rw-r--r--src/tools.c139
-rw-r--r--src/tools.h2
4 files changed, 129 insertions, 14 deletions
diff --git a/src/lanes.c b/src/lanes.c
index eebe06a..3e906c0 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -2303,6 +2303,7 @@ static const struct luaL_reg lanes_functions [] = {
2303 {"linda", LG_linda}, 2303 {"linda", LG_linda},
2304 {"now_secs", LG_now_secs}, 2304 {"now_secs", LG_now_secs},
2305 {"wakeup_conv", LG_wakeup_conv}, 2305 {"wakeup_conv", LG_wakeup_conv},
2306 {"nameof", luaG_nameof},
2306 {"_single", LG__single}, 2307 {"_single", LG__single},
2307 {NULL, NULL} 2308 {NULL, NULL}
2308}; 2309};
diff --git a/src/lanes.lua b/src/lanes.lua
index 5aeeaf4..d1082af 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -564,6 +564,7 @@ end
564 lanes.gen = gen 564 lanes.gen = gen
565 lanes.linda = mm.linda 565 lanes.linda = mm.linda
566 lanes.cancel_error = mm.cancel_error 566 lanes.cancel_error = mm.cancel_error
567 lanes.nameof = mm.nameof
567 lanes.timer = timer 568 lanes.timer = timer
568 lanes.genlock = genlock 569 lanes.genlock = genlock
569 lanes.genatomic = genatomic 570 lanes.genatomic = genatomic
diff --git a/src/tools.c b/src/tools.c
index ee2a1ca..65c70bf 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -1200,38 +1200,149 @@ static void push_cached_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, ui
1200} 1200}
1201 1201
1202/* 1202/*
1203 * Return some name helping to identify an object
1204 */
1205int discover_object_name_recur( lua_State* L, int _shortest, int _length)
1206{
1207 int const what = 1; // o "r" {c} {fqn} ... {?}
1208 int const result = 2;
1209 int const cache = 3;
1210 int const fqn = 4;
1211 // no need to scan this table if the name we will discover is longer than one we already know
1212 if( _shortest <= _length + 1)
1213 {
1214 return _shortest;
1215 }
1216 STACK_GROW( L, 3);
1217 STACK_CHECK(L)
1218 // stack top contains the table to search in
1219 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?}
1220 lua_rawget( L, cache); // o "r" {c} {fqn} ... {?} nil/1
1221 // if table is already visited, we are done
1222 if( !lua_isnil( L, -1))
1223 {
1224 lua_pop( L, 1); // o "r" {c} {fqn} ... {?}
1225 return _shortest;
1226 }
1227 // examined table is not in the cache, add it now
1228 lua_pop( L, 1); // o "r" {c} {fqn} ... {?}
1229 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?}
1230 lua_pushinteger( L, 1); // o "r" {c} {fqn} ... {?} {?} 1
1231 lua_rawset( L, cache); // o "r" {c} {fqn} ... {?}
1232 // scan table contents
1233 lua_pushnil( L); // o "r" {c} {fqn} ... {?} nil
1234 while( lua_next( L, -2)) // o "r" {c} {fqn} ... {?} k v
1235 {
1236 //char const *const key = lua_tostring( L, -2); // only for debugging (BEWARE, IT MAY CHANGE THE VALUE IF IT IS CONVERTIBLE, AND WRECK THE LOOP ITERATION PROCESS!)
1237 // append key name to fqn stack
1238 ++ _length;
1239 lua_pushvalue( L, -2); // o "r" {c} {fqn} ... {?} k v k
1240 lua_rawseti( L, fqn, _length); // o "r" {c} {fqn} ... {?} k v
1241 if( lua_rawequal( L, -1, what)) // is it what we are looking for?
1242 {
1243 // update shortest name
1244 if( _length < _shortest)
1245 {
1246 _shortest = _length;
1247 luaG_pushFQN( L, fqn, _length); // o "r" {c} {fqn} ... {?} k v "fqn"
1248 lua_replace( L, result); // o "r" {c} {fqn} ... {?} k v
1249 }
1250 // no need to search further at this level
1251 lua_pop( L, 2); // o "r" {c} {fqn} ... {?}
1252 break;
1253 }
1254 else if( lua_istable( L, -1))
1255 {
1256 _shortest = discover_object_name_recur( L, _shortest, _length);
1257 }
1258 // make ready for next iteration
1259 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k
1260 // remove name from fqn stack
1261 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k nil
1262 lua_rawseti( L, fqn, _length); // o "r" {c} {fqn} ... {?} k
1263 -- _length;
1264 } // o "r" {c} {fqn} ... {?}
1265 // remove the visited table from the cache, in case a shorter path to the searched object exists
1266 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?}
1267 lua_pushnil( L); // o "r" {c} {fqn} ... {?} {?} nil
1268 lua_rawset( L, cache); // o "r" {c} {fqn} ... {?}
1269 STACK_END( L, 0)
1270 return _shortest;
1271}
1272
1273/*
1274 * "type", "name" = lanes.nameof( o)
1275 */
1276int luaG_nameof( lua_State* L)
1277{
1278 int what = lua_gettop( L);
1279 if( what > 1)
1280 {
1281 luaL_argerror( L, what, "too many arguments.");
1282 }
1283
1284 // numbers, strings, booleans and nil can't be identified
1285 if( lua_type( L, 1) < LUA_TTABLE)
1286 {
1287 lua_pushstring( L, luaL_typename( L, 1)); // o "type"
1288 lua_insert( L, -2); // "type" o
1289 return 2;
1290 }
1291 STACK_GROW( L, 4);
1292 // this slot will contain the shortest name we found when we are done
1293 lua_pushnil( L); // o nil
1294 // push a cache that will contain all already visited tables
1295 lua_newtable( L); // o nil {c}
1296 // push a table whose contents are strings that, when concatenated, produce unique name
1297 lua_newtable( L); // o nil {c} {fqn}
1298 // this is where we start the search
1299 lua_pushvalue( L, LUA_GLOBALSINDEX); // o nil {c} {fqn} _G
1300 (void) discover_object_name_recur( L, 6666, 0);
1301 lua_pop( L, 3); // o "result"
1302 lua_pushstring( L, luaL_typename( L, 1)); // o "result" "type"
1303 lua_replace( L, -3); // "type" "result"
1304 return 2;
1305}
1306
1307/*
1203* Push a looked-up native/LuaJIT function. 1308* Push a looked-up native/LuaJIT function.
1204*/ 1309*/
1205static void lookup_native_func( lua_State *L2, lua_State *L, uint_t i) 1310static void lookup_native_func( lua_State *L2, lua_State *L, uint_t i)
1206{ 1311{
1207 char const *fqn; 1312 char const *fqn; // L // L2
1208 size_t len; 1313 size_t len;
1209 _ASSERT_L( L, lua_isfunction( L, i)); 1314 _ASSERT_L( L, lua_isfunction( L, i)); // ... f ...
1210 STACK_CHECK( L) 1315 STACK_CHECK( L)
1211 STACK_CHECK( L2)
1212 // fetch the name from the source state's lookup table 1316 // fetch the name from the source state's lookup table
1213 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // {} 1317 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // ... f ... {}
1214 _ASSERT_L( L, lua_istable( L, -1)); 1318 _ASSERT_L( L, lua_istable( L, -1));
1215 lua_pushvalue( L, i); // {} f 1319 lua_pushvalue( L, i); // ... f ... {} f
1216 lua_rawget( L, -2); // {} "f.q.n" 1320 lua_rawget( L, -2); // ... f ... {} "f.q.n"
1217 fqn = lua_tolstring( L, -1, &len); 1321 fqn = lua_tolstring( L, -1, &len);
1322 // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database
1323 lua_pop( L, 2); // ... f ...
1218 if( !fqn) 1324 if( !fqn)
1219 { 1325 {
1220 luaL_error( L, "function not found in origin transfer database."); 1326 lua_pushvalue( L, i); // ... f ... f
1327 // try to discover the name of the function we want to send
1328 luaG_nameof( L); // ... f ... "type" "name"
1329 (void) luaL_error( L, "%s %s not found in origin transfer database.", lua_tostring( L, -2), lua_tostring( L, -1));
1330 return;
1221 } 1331 }
1332 STACK_END( L, 0)
1222 // push the equivalent function in the destination's stack, retrieved from the lookup table 1333 // push the equivalent function in the destination's stack, retrieved from the lookup table
1223 lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_KEY); // {} 1334 STACK_CHECK( L2)
1335 lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_KEY); // {}
1224 _ASSERT_L( L2, lua_istable( L2, -1)); 1336 _ASSERT_L( L2, lua_istable( L2, -1));
1225 lua_pushlstring( L2, fqn, len); // {} "f.q.n" 1337 lua_pushlstring( L2, fqn, len); // {} "f.q.n"
1226 lua_pop( L, 2); // 1338 lua_rawget( L2, -2); // {} f
1227 lua_rawget( L2, -2); // {} f
1228 if( !lua_isfunction( L2, -1)) 1339 if( !lua_isfunction( L2, -1))
1229 { 1340 {
1230 luaL_error( L, "function %s not found in destination transfer database.", fqn); 1341 (void) luaL_error( L, "function %s not found in destination transfer database.", fqn);
1342 return;
1231 } 1343 }
1232 lua_remove( L2, -2); // f 1344 lua_remove( L2, -2); // f
1233 STACK_END( L2, 1) 1345 STACK_END( L2, 1)
1234 STACK_END( L, 0)
1235} 1346}
1236 1347
1237#define LOG_FUNC_INFO 0 1348#define LOG_FUNC_INFO 0
diff --git a/src/tools.h b/src/tools.h
index 67f9874..b8dc362 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -65,6 +65,8 @@ void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *deep_u
65int luaG_inter_copy( lua_State *L, lua_State *L2, uint_t n); 65int luaG_inter_copy( lua_State *L, lua_State *L2, uint_t n);
66int luaG_inter_move( lua_State *L, lua_State *L2, uint_t n); 66int luaG_inter_move( lua_State *L, lua_State *L2, uint_t n);
67 67
68int luaG_nameof( lua_State* L);
69
68// Lock for reference counter inc/dec locks (to be initialized by outside code) 70// Lock for reference counter inc/dec locks (to be initialized by outside code)
69// 71//
70extern MUTEX_T deep_lock; 72extern MUTEX_T deep_lock;