Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Split simgrid_lua.c in one source file per module
[simgrid.git] / src / bindings / lua / lua_state_cloner.c
index e5789ec..27a79d6 100644 (file)
@@ -13,7 +13,7 @@
 #include <lauxlib.h>
 #include <lualib.h>
 
-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua_state_cloner, lua, "Lua state management");
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua_state_cloner, bindings, "Lua state management");
 
 static void sglua_add_maestro_table(lua_State* L, int index, void* maestro_table_ptr);
 static void* sglua_get_maestro_table_ptr(lua_State* L, int index);
@@ -126,15 +126,30 @@ 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.
+ *
+ * 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
+ */
+void sglua_move_value(lua_State* src, lua_State* dst) {
+
+  sglua_copy_value(src, dst);
+  lua_pop(src, 1);
+}
+
+/**
+ * @brief Pushes onto the stack a copy of the value on top another stack.
  * If the value is a table, its content is copied recursively.
  *
- * TODO: add support of closures
+ * This function allows to move a value between two different global states.
  *
  * @param src the source state (not necessarily maestro)
  * @param dst the destination state
  */
-void sglua_move_value(lua_State* src, lua_State *dst) {
+void sglua_copy_value(lua_State* src, lua_State* dst) {
 
   luaL_checkany(src, -1);                  /* check the value to copy */
 
@@ -183,13 +198,10 @@ void sglua_move_value(lua_State* src, lua_State *dst) {
       break;
   }
 
-  /* the value has been copied to dst: remove it from src */
-  lua_pop(src, 1);
-
   indent -= 2;
   XBT_DEBUG("%sData copied", sglua_get_spaces(indent));
 
-  sglua_stack_dump("src after copying a value (should be ...): ", src);
+  sglua_stack_dump("src after copying a value (should be ... value): ", src);
   sglua_stack_dump("dst after copying a value (should be ... value): ", dst);
 }
 
@@ -377,22 +389,52 @@ 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 */
 
     s_sglua_buffer_t buffer;
-    buffer.capacity = 64;
+    buffer.capacity = 128; /* an empty function uses 77 bytes */
     buffer.size = 0;
     buffer.data = xbt_new(char, buffer.capacity);
 
     /* copy the binary chunk from src into a buffer */
-    int error = lua_dump(src, sglua_memory_writer, &buffer);
+    _XBT_GNUC_UNUSED int error = lua_dump(src, sglua_memory_writer, &buffer);
     xbt_assert(!error, "Failed to dump the function from the source state: error %d",
         error);
+    XBT_DEBUG("Fonction dumped: %zu bytes", buffer.size);
+
+    /*
+    fwrite(buffer.data, buffer.size, buffer.size, stderr);
+    fprintf(stderr, "\n");
+    */
 
     /* load the chunk into dst */
     error = luaL_loadbuffer(dst, buffer.data, buffer.size, "(dumped function)");
@@ -580,15 +622,13 @@ lua_State* sglua_clone_maestro(void) {
   /* create the table of known tables from maestro */
   lua_pushstring(L, "simgrid.maestro_tables");
                                             /* "simgrid.maestro_tables" */
-  lua_newtable(L);                          /* "simgrid.maestro_tables" maestrotbs*/
+  lua_newtable(L);                          /* "simgrid.maestro_tables" maestrotbs */
   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
+   * inherited like any global values */
+  /* luaL_openlibs(L); */
 
   XBT_DEBUG("New state created");