diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lanes.c | 1 | ||||
-rw-r--r-- | src/lanes.lua | 1 | ||||
-rw-r--r-- | src/tools.c | 139 | ||||
-rw-r--r-- | src/tools.h | 2 |
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 | */ | ||
1205 | int 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 | */ | ||
1276 | int 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 | */ |
1205 | static void lookup_native_func( lua_State *L2, lua_State *L, uint_t i) | 1310 | static 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 | |||
65 | int luaG_inter_copy( lua_State *L, lua_State *L2, uint_t n); | 65 | int luaG_inter_copy( lua_State *L, lua_State *L2, uint_t n); |
66 | int luaG_inter_move( lua_State *L, lua_State *L2, uint_t n); | 66 | int luaG_inter_move( lua_State *L, lua_State *L2, uint_t n); |
67 | 67 | ||
68 | int 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 | // |
70 | extern MUTEX_T deep_lock; | 72 | extern MUTEX_T deep_lock; |