Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Lua: add support of closures to the state cloner
[simgrid.git] / src / bindings / lua / lua_state_cloner.c
index fbe640a..4e35f18 100644 (file)
@@ -30,24 +30,6 @@ static void sglua_copy_lightuserdata(lua_State* src, lua_State* dst);
 static void sglua_copy_userdata(lua_State* src, lua_State* dst);
 static void sglua_copy_thread(lua_State* src, lua_State* dst);
 
-/**
- * @brief Returns the father of a state, i.e. the state that created it.
- * @param L a Lua state
- * @return its father, or NULL if the state was not created by sglua_clone_state()
- */
-static lua_State* sglua_get_father(lua_State* L) {
-
-                                  /* ... */
-  lua_pushstring(L, "simgrid.father");
-                                  /* ... "simgrid.father" */
-  lua_rawget(L, LUA_REGISTRYINDEX);
-                                  /* ... father */
-  lua_State* father = lua_touserdata(L, -1);
-  lua_pop(L, 1);
-                                  /* ... */
-  return father;
-}
-
 /**
  * @brief Adds a reference to a maestro table to the list of known maestro
  * tables of a state.
@@ -66,7 +48,9 @@ void sglua_add_maestro_table(lua_State* L, int index, void* maestro_table_ptr) {
                                   /* ... */
   lua_pushvalue(L, index);
                                   /* ... table */
-  lua_getfield(L, LUA_REGISTRYINDEX, "simgrid.maestro_tables");
+  lua_pushstring(L, "simgrid.maestro_tables");
+                                  /* ... table "simgrid.maestro_tables" */
+  lua_rawget(L, LUA_REGISTRYINDEX);
                                   /* ... table maestrotbs */
   lua_pushvalue(L, -2);
                                   /* ... table maestrotbs table */
@@ -96,20 +80,22 @@ static void* sglua_get_maestro_table_ptr(lua_State* L, int index) {
 
   void* maestro_table_ptr = NULL;
                                   /* ... */
+  lua_pushvalue(L, index);
+                                  /* ... table */
   lua_pushstring(L, "simgrid.maestro_tables");
-                                  /* ... "simgrid.maestro_tables" */
+                                  /* ... table "simgrid.maestro_tables" */
   lua_rawget(L, LUA_REGISTRYINDEX);
-                                  /* ... maestrotbs */
-  lua_pushvalue(L, index);
-                                  /* ... maestrotbs table */
+                                  /* ... table maestrotbs */
+  lua_pushvalue(L, -2);
+                                  /* ... table maestrotbs table */
   lua_gettable(L, -2);
-                                  /* ... maestrotbs tableptr/nil */
+                                  /* ... table maestrotbs tableptr/nil */
   if (!lua_isnil(L, -1)) {
-                                  /* ... maestrotbs tableptr */
+                                  /* ... table maestrotbs tableptr */
     maestro_table_ptr = (void*) lua_topointer(L, -1);
   }
 
-  lua_pop(L, 2);
+  lua_pop(L, 3);
                                   /* ... */
   return maestro_table_ptr;
 }
@@ -140,10 +126,10 @@ static void sglua_get_table_by_ptr(lua_State* L, void* maestro_table_ptr) {
 /**
  * @brief Pops a value from the stack of a source state and pushes it on the
  * stack of another state.
- *
  * If the value is a table, its content is copied recursively.
  *
- * TODO: add support of closures
+ * This function is similar to lua_xmove() but it allows to move a value
+ * between two different global states.
  *
  * @param src the source state (not necessarily maestro)
  * @param dst the destination state
@@ -269,12 +255,17 @@ static void sglua_copy_table(lua_State* src, lua_State* dst) {
     table_ptr = (void*) lua_topointer(src, -1);
 
     if (!sglua_is_maestro(src)) {
-      XBT_DEBUG("Using a non-maestro table pointer");
+      XBT_DEBUG("%sMaestro does not know this table",
+          sglua_get_spaces(indent));
     }
   }
-  else if (sglua_is_maestro(src)) {
+
+  if (sglua_is_maestro(src)) {
     /* register the table in maestro itself */
+    XBT_DEBUG("%sKeeping track of this table in maestro itself",
+        sglua_get_spaces(indent));
     sglua_add_maestro_table(src, -1, table_ptr);
+    xbt_assert(sglua_get_maestro_table_ptr(src, -1) == table_ptr);
   }
 
   /* to avoid infinite recursion, see if this table is already known by dst */
@@ -301,6 +292,7 @@ static void sglua_copy_table(lua_State* src, lua_State* dst) {
     /* FIXME: we may have added a table with a non-maestro pointer, is this a
        problem? */
     XBT_DEBUG("%sTable marked as known", sglua_get_spaces(indent));
+    xbt_assert(sglua_get_maestro_table_ptr(dst, -1) == table_ptr);
 
     sglua_stack_dump("dst after marking the table as known (should be ... table): ", dst);
 
@@ -377,7 +369,7 @@ static void sglua_copy_table(lua_State* src, lua_State* dst) {
  * @brief Copies the function on the top of src to the top of dst.
  *
  * It can be a Lua function or a C function.
- * Copying upvalues is not implemented yet (TODO).
+ * Copying upvalues is not implemented yet.
  *
  * @param src source state
  * @param dst destination state
@@ -385,9 +377,33 @@ static void sglua_copy_table(lua_State* src, lua_State* dst) {
 static void sglua_copy_function(lua_State* src, lua_State* dst) {
 
   if (lua_iscfunction(src, -1)) {
-    /* it's a C function: just copy the pointer */
-    lua_CFunction f = lua_tocfunction(src, -1);
-    lua_pushcfunction(dst, f);
+    /* it's a C function */
+
+    XBT_DEBUG("It's a C function");
+    sglua_stack_dump("src before copying upvalues: ", src);
+
+    /* get the function pointer */
+    int function_index = lua_gettop(src);
+    lua_CFunction f = lua_tocfunction(src, function_index);
+
+    /* copy the upvalues */
+    int i = 0;
+    const char* upvalue_name = NULL;
+    do {
+      i++;
+      upvalue_name = lua_getupvalue(src, function_index, i);
+
+      if (upvalue_name != NULL) {
+        XBT_DEBUG("Upvalue %s", upvalue_name);
+        sglua_move_value(src, dst);
+      }
+    } while (upvalue_name != NULL);
+
+    sglua_stack_dump("src before copying pointer: ", src);
+
+    /* set the function */
+    lua_pushcclosure(dst, f, i - 1);
+    XBT_DEBUG("Function pointer copied");
   }
   else {
     /* it's a Lua function: dump it from src */
@@ -592,11 +608,9 @@ lua_State* sglua_clone_maestro(void) {
   lua_rawset(L, LUA_REGISTRYINDEX);
                                             /* -- */
 
-  /* open the standard libs (theoretically, this is not necessary as they can
-   * be inherited like any global values, but without a proper support of
-   * closures, iterators like ipairs don't work). */
-  XBT_DEBUG("Metatable of globals and registry set, opening standard libraries now");
-  luaL_openlibs(L);
+  /* opening the standard libs is not necessary as they are
+   * be inherited like any global values */
+  /* luaL_openlibs(L); */
 
   XBT_DEBUG("New state created");