Advertisement
Guest User

lua 5.1 latebound functions

a guest
Jul 16th, 2019
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.65 KB | None | 0 0
  1. #if 0
  2. LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
  3.                                 const luaL_Reg *l) {
  4.   luaI_openlib(L, libname, l, 0);
  5. }
  6. #else /* late bind cfunction tables to save ram needs pairs and ipairs from 5.2 */
  7. static int latebind_func_index(lua_State *L)
  8. {
  9.   const luaL_Reg *llib;
  10.   /* name @ top of stack 1(basetable;name)-1*/
  11.   const char *name = lua_tostring(L, -1);
  12.  
  13.   lua_pushstring (L, "__latebind");/* basetable;name;__latebind;*/
  14.   lua_rawget (L, -3);/* basetable;name;__latebind(t);*/
  15.  
  16.   luaL_argcheck(L, lua_istable(L, -3) && lua_istable(L, -1), 1,
  17.                 "__latebind table expected");
  18.   /* (btable;name;__latebind(t)) */
  19.  
  20.   /* lookup late bound func(s), lua_objlen allows check of multiple luaL_Reg */
  21.   for(int i = lua_objlen(L, -1); i > 0; i--) {
  22.     lua_rawgeti (L, -1, i);/* btable;name;__lb(t);llib*/
  23.     llib = (const luaL_Reg *) lua_touserdata (L, -1);
  24.     lua_pop(L, 1); /* (btable;name;__lb(t);llib) -> (btable;name;__lb(t)) */
  25.  
  26.     if(!llib)
  27.       continue;
  28.  
  29.     for (; llib->name; llib++) {
  30.       if(!name || strcmp(name, llib->name) == 0) {
  31.         /* don't overwrite existing keys within basetable */
  32.         lua_pushstring(L, llib->name); /* (btable;name;__lb(t);llib->name) */
  33.         lua_rawget(L, -4); /* (btable;name;__lb(t);btable[func]?) */
  34.  
  35.         if(lua_isnil(L, -1)) {
  36.           /* if function is used it is added to the base table */
  37.           lua_pop(L, 1);
  38.           lua_pushcclosure(L, llib->func, 0); /* (btable;name;__lb(t);llib->func) */
  39.         }
  40.  
  41.         if(!name) /* nil name binds all functions in table immediately */
  42.           lua_setfield(L, -4, llib->name); /* (btable;name;mtable) */
  43.         else {
  44.           lua_pushvalue(L, -1); /* dupe closure or existing func */
  45.           /* (btable;name;__lb(t);llib->func;llib->func) */
  46.           lua_setfield(L, -5, llib->name); /* (btable;name;__lb(t);llib->func) */
  47.           /* returns the closure */
  48.           return 1;
  49.         }
  50.       }
  51.     }
  52.   }
  53.  
  54.   lua_pop(L, 2); /* (btable;name;__lb(t)) -> (btable) */
  55.   if(!name) {
  56.     lua_pushnil(L); /* remove metatable (btable;name;__lb(t);nil)*/
  57.     lua_setmetatable(L, -2);
  58.     lua_pushnil(L); /* remove __latebind table*/
  59.     lua_setfield (L, -2, "__latebind");
  60.   }
  61.  
  62.   return 0;
  63. }
  64.  
  65.  
  66. static int latebind_func_pairs(lua_State *L)
  67. {
  68.   /* basetable @ top of stack 1(basetable)-1 */
  69.   luaL_argcheck(L, lua_istable(L, 1), 1, "table expected");
  70.   lua_getglobal(L, "pairs"); /* function to be called / returned (btable;pairs) */
  71.  
  72.   lua_createtable(L, 0, 15); /* btable;pairs;newtable; */
  73.   /* clone base table */
  74.   lua_pushnil(L); /* first key */
  75.   while(lua_next(L, 1) != 0) {
  76.     /* (btable;pairs;ntable;k;v) */
  77.     lua_pushvalue(L, -2); /* dupe key Stk = (..;k;v -> ..k;v;k)*/
  78.     lua_insert(L, -2); /* Stk = (..k;k;v) */
  79.     lua_rawset(L, 3); /* btable;pairs;ntable;k */
  80.   }
  81.  
  82.   lua_pushnil(L); /*nil name retrieves all unbound late bound functions */
  83.   latebind_func_index(L);/* (btable;pairs;ntable;nil) -> (btable;pairs;ntable) */
  84.  
  85.   /* (btable;pairs;ntable) */
  86.   lua_call(L, 1, 3); /* pairs(ntable) -> (btable;iter;state;value) */
  87.  
  88.   return 3;
  89. }
  90.  
  91.  
  92. LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
  93.                                 const luaL_Reg *l) {
  94.   if(!libname)
  95.   {
  96.     /* if there is no libname register normally */
  97.     luaI_openlib(L, libname, l, 0);
  98.     return;
  99.   }
  100.  
  101.   /* store empty table instead of passed luaL_Reg table */
  102.   static const struct luaL_reg late_lib [] =
  103.   {
  104.     {NULL, NULL}
  105.   };
  106.  
  107.   static const struct luaL_reg late_meta [] =
  108.   {
  109.     {"__index", latebind_func_index},
  110.     {"__pairs", latebind_func_pairs},
  111.     {"__call", latebind_func_index}, /* allows t("func") -- nil binds all */
  112.     {NULL, NULL}
  113.   };
  114.  
  115.   //libsize_storenames(L, libname, l); /* store func names */ //IN BINARY STRINGS
  116.   luaI_openlib(L, libname, late_lib, 0); /* basetable; */
  117.  
  118.   luaL_findtable(L, -1,"__latebind", 0); /* create table if doesn't exist */
  119.   /* basetable;__latebind(t); */
  120.   /* save pointer to real luaL_reg */
  121.   lua_pushlightuserdata (L, (void *) l); /*basetable;__lb(t);userdata;*/
  122.   lua_rawseti(L, -2, lua_objlen(L, -2) + 1); /*lb(t)[n] = userdata */
  123.  
  124.   lua_pop(L, 1);/* (basetable;__latebind(t)) -> (basetable) */
  125.  
  126.   if(luaL_newmetatable(L, "META_LATEBIND"))
  127.   {
  128.     luaI_openlib(L, NULL, late_meta, 0); /*basetable;metatable*/
  129.     lua_pushvalue(L, -1); /* dupe the metatable (basetable;mt;mt) */
  130.     lua_setfield (L, -2, "__metatable"); /* metatable[__metatable] = metatable */
  131.   }
  132.  
  133.   lua_setmetatable(L, -2); /* (basetable;mt) -> (basetable+mtable) */
  134.   /* base table is top of stack (basetable) */
  135. }
  136. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement