Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Nice joke.
[simgrid.git] / src / bindings / lua / simgrid_lua.c
1 /* Copyright (c) 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 /* SimGrid Lua bindings                                                     */
8
9 #include "simgrid_lua.h"
10 #include "lua_state_cloner.h"
11 #include "lua_utils.h"
12
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua, bindings, "Lua Bindings");
14
15 #define TASK_MODULE_NAME "simgrid.task"
16 #define HOST_MODULE_NAME "simgrid.host"
17 // Surf (bypass XML)
18 #define LINK_MODULE_NAME "simgrid.link"
19 #define ROUTE_MODULE_NAME "simgrid.route"
20 #define PLATF_MODULE_NAME "simgrid.platf"
21
22 static lua_State* sglua_maestro_state;
23
24 static void register_c_functions(lua_State *L);
25
26 /**
27  * \brief Like luaL_checkudata, with additional debug logs.
28  * \param L a lua state
29  * \param ud index of the userdata to check in the stack
30  * \param tname key of the metatable of this userdata in the registry
31  */
32 static void* my_checkudata(lua_State* L, int ud, const char* tname) {
33
34   XBT_DEBUG("Checking the userdata: ud = %d", ud);
35   sglua_stack_dump("my_checkudata: ", L);
36   void* p = lua_touserdata(L, ud);
37   lua_getfield(L, LUA_REGISTRYINDEX, tname);
38   const void* correct_mt = lua_topointer(L, -1);
39
40   int has_mt = lua_getmetatable(L, ud);
41   XBT_DEBUG("Checking the userdata: has metatable ? %d", has_mt);
42   const void* actual_mt = NULL;
43   if (has_mt) {
44     actual_mt = lua_topointer(L, -1);
45     lua_pop(L, 1);
46   }
47   XBT_DEBUG("Checking the task's metatable: expected %p, found %p", correct_mt, actual_mt);
48   sglua_stack_dump("my_checkudata: ", L);
49
50   if (p == NULL || !lua_getmetatable(L, ud) || !lua_rawequal(L, -1, -2))
51     luaL_typerror(L, ud, tname);
52   lua_pop(L, 2);
53   return p;
54 }
55
56 /**
57  * @brief Ensures that a value is a valid task and returns it.
58  * @param L a Lua state
59  * @param index an index in the Lua stack
60  * @return the task at this index
61  */
62 static m_task_t sglua_checktask(lua_State* L, int index)
63 {
64   sglua_stack_dump("check task: ", L);
65   luaL_checktype(L, index, LUA_TTABLE);
66                                   /* ... task ... */
67   lua_getfield(L, index, "__simgrid_task");
68                                   /* ... task ... ctask */
69   m_task_t task = *((m_task_t*) luaL_checkudata(L, -1, TASK_MODULE_NAME));
70   lua_pop(L, 1);
71                                   /* ... task ... */
72
73   if (task == NULL) {
74     luaL_error(L, "This task was sent to someone else, you cannot access it anymore");
75   }
76
77   return task;
78 }
79
80 /* ********************************************************************************* */
81 /*                           wrapper functions                                       */
82 /* ********************************************************************************* */
83
84 /**
85  * \brief Creates a new task and leaves it onto the stack.
86  *
87  * Lua arguments:
88  * - task name (string)
89  * - computation size (integer)
90  * - communication size (integer)
91  */
92 static int l_task_new(lua_State* L)
93 {
94   XBT_DEBUG("Task new");
95   const char* name = luaL_checkstring(L, 1);
96   int comp_size = luaL_checkint(L, 2);
97   int msg_size = luaL_checkint(L, 3);
98                                   /* name comp comm */
99   lua_settop(L, 0);
100                                   /* -- */
101   m_task_t msg_task = MSG_task_create(name, comp_size, msg_size, NULL);
102
103   lua_newtable(L);
104                                   /* task */
105   m_task_t* lua_task = (m_task_t*) lua_newuserdata(L, sizeof(m_task_t));
106                                   /* task ctask */
107   *lua_task = msg_task;
108   luaL_getmetatable(L, TASK_MODULE_NAME);
109                                   /* task ctask mt */
110   lua_setmetatable(L, -2);
111                                   /* task ctask */
112   lua_setfield(L, -2, "__simgrid_task");
113                                   /* task */
114   return 1;
115 }
116
117 static int l_task_get_name(lua_State* L)
118 {
119   m_task_t task = sglua_checktask(L, 1);
120   lua_pushstring(L, MSG_task_get_name(task));
121   return 1;
122 }
123
124 static int l_task_computation_duration(lua_State* L)
125 {
126   m_task_t task = sglua_checktask(L, 1);
127   lua_pushnumber(L, MSG_task_get_compute_duration(task));
128   return 1;
129 }
130
131 static int l_task_execute(lua_State* L)
132 {
133   m_task_t task = sglua_checktask(L, 1);
134   int res = MSG_task_execute(task);
135   lua_pushnumber(L, res);
136   return 1;
137 }
138
139 static int l_task_send(lua_State* L)
140 {
141   m_task_t task = sglua_checktask(L, 1);
142   const char* mailbox = luaL_checkstring(L, 2);
143                                   /* task mailbox */
144   lua_settop(L, 1);
145                                   /* task */
146   /* copy my stack into the task, so that the receiver can copy the lua task */
147   MSG_task_set_data(task, L);
148   MSG_error_t res = MSG_task_send(task, mailbox);
149   while (MSG_task_get_data(task) != NULL) {
150     /* don't mess up with my stack: the receiver didn't copy the data yet */
151     MSG_process_sleep(0);
152   }
153
154   if (res == MSG_OK) {
155     /* the receiver is the owner of the task and may destroy it:
156      * remove the C task on my side so that I don't garbage collect it */
157     lua_getfield(L, 1, "__simgrid_task");
158                                   /* task ctask */
159     m_task_t* udata = (m_task_t*) luaL_checkudata(L, -1, TASK_MODULE_NAME);
160     *udata = NULL;
161     lua_pop(L, 1);
162                                   /* task */
163   }
164   else {
165     switch (res) {
166     case MSG_TIMEOUT:
167       XBT_DEBUG("MSG_task_send failed : Timeout");
168       break;
169     case MSG_TRANSFER_FAILURE:
170       XBT_DEBUG("MSG_task_send failed : Transfer Failure");
171       break;
172     case MSG_HOST_FAILURE:
173       XBT_DEBUG("MSG_task_send failed : Host Failure ");
174       break;
175     default:
176       XBT_ERROR
177           ("MSG_task_send failed : Unexpected error , please report this bug");
178       break;
179     }
180   }
181   return 0;
182 }
183
184 static int l_task_recv_with_timeout(lua_State *L)
185 {
186   m_task_t task = NULL;
187   const char* mailbox = luaL_checkstring(L, 1);
188   int timeout = luaL_checknumber(L, 2);
189                                   /* mailbox timeout */
190   lua_settop(L, 0);
191                                   /* -- */
192   MSG_error_t res = MSG_task_receive_with_timeout(&task, mailbox, timeout);
193
194   if (res == MSG_OK) {
195     /* copy the data directly from sender's stack */
196     lua_State* sender_stack = MSG_task_get_data(task);
197     sglua_copy_value(sender_stack, L);
198                                   /* task */
199     MSG_task_set_data(task, NULL);
200   }
201   else {
202     switch (res) {
203     case MSG_TIMEOUT:
204       XBT_DEBUG("MSG_task_receive failed : Timeout");
205       break;
206     case MSG_TRANSFER_FAILURE:
207       XBT_DEBUG("MSG_task_receive failed : Transfer Failure");
208       break;
209     case MSG_HOST_FAILURE:
210       XBT_DEBUG("MSG_task_receive failed : Host Failure ");
211       break;
212     default:
213       XBT_ERROR("MSG_task_receive failed : Unexpected error , please report this bug");
214       break;
215     }
216     lua_pushnil(L);
217                                   /* nil */
218   }
219                                   /* task/nil */
220   return 1;
221 }
222
223 static int l_task_recv(lua_State * L)
224 {
225   lua_pushnumber(L, -1.0);
226   return l_task_recv_with_timeout(L);
227 }
228
229 static const luaL_reg task_functions[] = {
230   {"new", l_task_new},
231   {"name", l_task_get_name},
232   {"computation_duration", l_task_computation_duration},
233   {"execute", l_task_execute},
234   {"send", l_task_send},
235   {"recv", l_task_recv},
236   {"recv_timeout", l_task_recv_with_timeout},
237   {NULL, NULL}
238 };
239
240 static int l_task_gc(lua_State* L)
241 {
242                                   /* ctask */
243   m_task_t task = *((m_task_t*) luaL_checkudata(L, 1, TASK_MODULE_NAME));
244   /* the task is NULL if I sent it to someone else */
245   if (task != NULL) {
246     MSG_task_destroy(task);
247   }
248   return 0;
249 }
250
251 static int l_task_tostring(lua_State* L)
252 {
253   m_task_t task = sglua_checktask(L, 1);
254   lua_pushfstring(L, "Task: %p", task);
255   return 1;
256 }
257
258 static const luaL_reg task_meta[] = {
259   {"__gc", l_task_gc},
260   {"__tostring", l_task_tostring},
261   {NULL, NULL}
262 };
263
264 /**
265  * Host
266  */
267 static m_host_t sglua_checkhost(lua_State * L, int index)
268 {
269   m_host_t *pi, ht;
270   luaL_checktype(L, index, LUA_TTABLE);
271   lua_getfield(L, index, "__simgrid_host");
272   pi = (m_host_t *) luaL_checkudata(L, lua_gettop(L), HOST_MODULE_NAME);
273   if (pi == NULL)
274     luaL_typerror(L, index, HOST_MODULE_NAME);
275   ht = *pi;
276   if (!ht)
277     luaL_error(L, "null Host");
278   lua_pop(L, 1);
279   return ht;
280 }
281
282 static int l_host_get_by_name(lua_State * L)
283 {
284   const char *name = luaL_checkstring(L, 1);
285   XBT_DEBUG("Getting Host from name...");
286   m_host_t msg_host = MSG_get_host_by_name(name);
287   if (!msg_host) {
288     luaL_error(L, "null Host : MSG_get_host_by_name failed");
289   }
290   lua_newtable(L);              /* create a table, put the userdata on top of it */
291   m_host_t *lua_host = (m_host_t *) lua_newuserdata(L, sizeof(m_host_t));
292   *lua_host = msg_host;
293   luaL_getmetatable(L, HOST_MODULE_NAME);
294   lua_setmetatable(L, -2);
295   lua_setfield(L, -2, "__simgrid_host");        /* put the userdata as field of the table */
296   /* remove the args from the stack */
297   lua_remove(L, 1);
298   return 1;
299 }
300
301 static int l_host_get_name(lua_State * L)
302 {
303   m_host_t ht = sglua_checkhost(L, -1);
304   lua_pushstring(L, MSG_host_get_name(ht));
305   return 1;
306 }
307
308 static int l_host_number(lua_State * L)
309 {
310   lua_pushnumber(L, MSG_get_host_number());
311   return 1;
312 }
313
314 static int l_host_at(lua_State * L)
315 {
316   int index = luaL_checkinteger(L, 1);
317   m_host_t host = MSG_get_host_table()[index - 1];      // lua indexing start by 1 (lua[1] <=> C[0])
318   lua_newtable(L);              /* create a table, put the userdata on top of it */
319   m_host_t *lua_host = (m_host_t *) lua_newuserdata(L, sizeof(m_host_t));
320   *lua_host = host;
321   luaL_getmetatable(L, HOST_MODULE_NAME);
322   lua_setmetatable(L, -2);
323   lua_setfield(L, -2, "__simgrid_host");        /* put the userdata as field of the table */
324   return 1;
325
326 }
327
328 static int l_host_self(lua_State * L)
329 {
330                                   /* -- */
331   m_host_t host = MSG_host_self();
332   lua_newtable(L);
333                                   /* table */
334   m_host_t* lua_host = (m_host_t*) lua_newuserdata(L, sizeof(m_host_t));
335                                   /* table ud */
336   *lua_host = host;
337   luaL_getmetatable(L, HOST_MODULE_NAME);
338                                   /* table ud mt */
339   lua_setmetatable(L, -2);
340                                   /* table ud */
341   lua_setfield(L, -2, "__simgrid_host");
342                                   /* table */
343   return 1;
344 }
345
346 static int l_host_get_property_value(lua_State * L)
347 {
348   m_host_t ht = sglua_checkhost(L, -2);
349   const char *prop = luaL_checkstring(L, -1);
350   lua_pushstring(L,MSG_host_get_property_value(ht,prop));
351   return 1;
352 }
353
354 static int l_host_sleep(lua_State *L)
355 {
356   int time = luaL_checknumber(L, -1);
357   MSG_process_sleep(time);
358   return 1;
359 }
360
361 static int l_host_destroy(lua_State *L)
362 {
363   m_host_t ht = sglua_checkhost(L, -1);
364   __MSG_host_destroy(ht);
365   return 1;
366 }
367
368 /* ********************************************************************************* */
369 /*                           lua_stub_generator functions                            */
370 /* ********************************************************************************* */
371
372 xbt_dict_t process_function_set;
373 xbt_dynar_t process_list;
374 xbt_dict_t machine_set;
375 static s_process_t process;
376
377 void s_process_free(void *process)
378 {
379   s_process_t *p = (s_process_t *) process;
380   int i;
381   for (i = 0; i < p->argc; i++)
382     free(p->argv[i]);
383   free(p->argv);
384   free(p->host);
385 }
386
387 static int gras_add_process_function(lua_State * L)
388 {
389   const char *arg;
390   const char *process_host = luaL_checkstring(L, 1);
391   const char *process_function = luaL_checkstring(L, 2);
392
393   if (xbt_dict_is_empty(machine_set)
394       || xbt_dict_is_empty(process_function_set)
395       || xbt_dynar_is_empty(process_list)) {
396     process_function_set = xbt_dict_new();
397     process_list = xbt_dynar_new(sizeof(s_process_t), s_process_free);
398     machine_set = xbt_dict_new();
399   }
400
401   xbt_dict_set(machine_set, process_host, NULL, NULL);
402   xbt_dict_set(process_function_set, process_function, NULL, NULL);
403
404   process.argc = 1;
405   process.argv = xbt_new(char *, 1);
406   process.argv[0] = xbt_strdup(process_function);
407   process.host = strdup(process_host);
408
409   lua_pushnil(L);
410   while (lua_next(L, 3) != 0) {
411     arg = lua_tostring(L, -1);
412     process.argc++;
413     process.argv =
414         xbt_realloc(process.argv, (process.argc) * sizeof(char *));
415     process.argv[(process.argc) - 1] = xbt_strdup(arg);
416
417     XBT_DEBUG("index = %f , arg = %s \n", lua_tonumber(L, -2),
418            lua_tostring(L, -1));
419     lua_pop(L, 1);
420   }
421   lua_pop(L, 1);
422   //add to the process list
423   xbt_dynar_push(process_list, &process);
424   return 0;
425 }
426
427
428 static int gras_generate(lua_State * L)
429 {
430   const char *project_name = luaL_checkstring(L, 1);
431   generate_sim(project_name);
432   generate_rl(project_name);
433   generate_makefile_local(project_name);
434   return 0;
435 }
436
437
438 // *********** Register Methods ******************************************* //
439
440 /*
441  * Host Methods
442  */
443 static const luaL_reg host_functions[] = {
444   {"get_by_name", l_host_get_by_name},
445   {"name", l_host_get_name},
446   {"number", l_host_number},
447   {"at", l_host_at},
448   {"self", l_host_self},
449   {"get_prop_value", l_host_get_property_value},
450   {"sleep", l_host_sleep},
451   {"destroy", l_host_destroy},
452   // Bypass XML Methods
453   {"set_function", console_set_function},
454   {"set_property", console_host_set_property},
455   {NULL, NULL}
456 };
457
458 static int l_host_tostring(lua_State * L)
459 {
460   lua_pushfstring(L, "Host :%p", lua_touserdata(L, 1));
461   return 1;
462 }
463
464 static const luaL_reg host_meta[] = {
465   {"__tostring", l_host_tostring},
466   {0, 0}
467 };
468
469 /*
470  * AS Methods
471  */
472 static const luaL_reg platf_functions[] = {
473     {"open", console_open},
474     {"close", console_close},
475     {"AS_open", console_AS_open},
476     {"AS_close", console_AS_close},
477     {"host_new", console_add_host},
478     {"link_new", console_add_link},
479     {"router_new", console_add_router},
480     {"route_new", console_add_route},
481     {NULL, NULL}
482 };
483
484 /*
485  * Environment related
486  */
487
488 /**
489  * @brief Runs a Lua function as a new simulated process.
490  * @param argc number of arguments of the function
491  * @param argv name of the Lua function and array of its arguments
492  * @return result of the function
493  */
494 static int run_lua_code(int argc, char **argv)
495 {
496   XBT_DEBUG("Run lua code %s", argv[0]);
497
498   lua_State *L = sglua_clone_maestro();
499   int res = 1;
500
501   /* start the function */
502   lua_getglobal(L, argv[0]);
503   xbt_assert(lua_isfunction(L, -1),
504               "The lua function %s does not seem to exist", argv[0]);
505
506   /* push arguments onto the stack */
507   int i;
508   for (i = 1; i < argc; i++)
509     lua_pushstring(L, argv[i]);
510
511   /* call the function */
512   _XBT_GNUC_UNUSED int err;
513   err = lua_pcall(L, argc - 1, 1, 0);
514   xbt_assert(err == 0, "error running function `%s': %s", argv[0],
515               lua_tostring(L, -1));
516
517   /* retrieve result */
518   if (lua_isnumber(L, -1)) {
519     res = lua_tonumber(L, -1);
520     lua_pop(L, 1);              /* pop returned value */
521   }
522
523   XBT_DEBUG("Execution of Lua code %s is over", (argv ? argv[0] : "(null)"));
524
525   return res;
526 }
527
528 static int launch_application(lua_State * L)
529 {
530   const char *file = luaL_checkstring(L, 1);
531   MSG_function_register_default(run_lua_code);
532   MSG_launch_application(file);
533   return 0;
534 }
535
536 static int create_environment(lua_State * L)
537 {
538   const char *file = luaL_checkstring(L, 1);
539   XBT_DEBUG("Loading environment file %s", file);
540   MSG_create_environment(file);
541   return 0;
542 }
543
544 static int debug(lua_State * L)
545 {
546   const char *str = luaL_checkstring(L, 1);
547   XBT_DEBUG("%s", str);
548   return 0;
549 }
550
551 static int info(lua_State * L)
552 {
553   const char *str = luaL_checkstring(L, 1);
554   XBT_INFO("%s", str);
555   return 0;
556 }
557
558 static int run(lua_State * L)
559 {
560   MSG_main();
561   return 0;
562 }
563
564 static int clean(lua_State * L)
565 {
566   MSG_clean();
567   return 0;
568 }
569
570 /*
571  * Bypass XML Parser (lua console)
572  */
573
574 /*
575  * Register platform for MSG
576  */
577 static int msg_register_platform(lua_State * L)
578 {
579   /* Tell Simgrid we dont wanna use its parser */
580   //surf_parse = console_parse_platform;
581   surf_parse_reset_callbacks();
582   MSG_create_environment(NULL);
583   return 0;
584 }
585
586 /*
587  * Register platform for Simdag
588  */
589
590 static int sd_register_platform(lua_State * L)
591 {
592   //surf_parse = console_parse_platform_wsL07;
593   surf_parse_reset_callbacks();
594   SD_create_environment(NULL);
595   return 0;
596 }
597
598 /*
599  * Register platform for gras
600  */
601 static int gras_register_platform(lua_State * L)
602 {
603   //surf_parse = console_parse_platform;
604   surf_parse_reset_callbacks();
605   gras_create_environment(NULL);
606   return 0;
607 }
608
609 /**
610  * Register applicaiton for MSG
611  */
612 static int msg_register_application(lua_State * L)
613 {
614   MSG_function_register_default(run_lua_code);
615   //surf_parse = console_parse_application;
616   MSG_launch_application(NULL);
617   return 0;
618 }
619
620 /*
621  * Register application for gras
622  */
623 static int gras_register_application(lua_State * L)
624 {
625   gras_function_register_default(run_lua_code);
626   //surf_parse = console_parse_application;
627   gras_launch_application(NULL);
628   return 0;
629 }
630
631 static const luaL_Reg simgrid_functions[] = {
632   {"create_environment", create_environment},
633   {"launch_application", launch_application},
634   {"debug", debug},
635   {"info", info},
636   {"run", run},
637   {"clean", clean},
638   /* short names */
639   {"platform", create_environment},
640   {"application", launch_application},
641   /* methods to bypass XML parser */
642   {"msg_register_platform", msg_register_platform},
643   {"sd_register_platform", sd_register_platform},
644   {"msg_register_application", msg_register_application},
645   {"gras_register_platform", gras_register_platform},
646   {"gras_register_application", gras_register_application},
647   /* gras sub generator method */
648   {"gras_set_process_function", gras_add_process_function},
649   {"gras_generate", gras_generate},
650   {NULL, NULL}
651 };
652
653 /* ********************************************************************************* */
654 /*                       module management functions                                 */
655 /* ********************************************************************************* */
656
657 #define LUA_MAX_ARGS_COUNT 10   /* maximum amount of arguments we can get from lua on command line */
658
659 int luaopen_simgrid(lua_State *L);     // Fuck gcc: we don't need that prototype
660
661 /**
662  * This function is called automatically by the Lua interpreter when some Lua code requires
663  * the "simgrid" module.
664  * @param L the Lua state
665  */
666 int luaopen_simgrid(lua_State *L)
667 {
668   XBT_DEBUG("luaopen_simgrid *****");
669
670   /* Get the command line arguments from the lua interpreter */
671   char **argv = malloc(sizeof(char *) * LUA_MAX_ARGS_COUNT);
672   int argc = 1;
673   argv[0] = (char *) "/usr/bin/lua";    /* Lie on the argv[0] so that the stack dumping facilities find the right binary. FIXME: what if lua is not in that location? */
674
675   lua_getglobal(L, "arg");
676   /* if arg is a null value, it means we use lua only as a script to init platform
677    * else it should be a table and then take arg in consideration
678    */
679   if (lua_istable(L, -1)) {
680     int done = 0;
681     while (!done) {
682       argc++;
683       lua_pushinteger(L, argc - 2);
684       lua_gettable(L, -2);
685       if (lua_isnil(L, -1)) {
686         done = 1;
687       } else {
688         xbt_assert(lua_isstring(L, -1),
689                     "argv[%d] got from lua is no string", argc - 1);
690         xbt_assert(argc < LUA_MAX_ARGS_COUNT,
691                     "Too many arguments, please increase LUA_MAX_ARGS_COUNT in %s before recompiling SimGrid if you insist on having more than %d args on command line",
692                     __FILE__, LUA_MAX_ARGS_COUNT - 1);
693         argv[argc - 1] = (char *) luaL_checkstring(L, -1);
694         lua_pop(L, 1);
695         XBT_DEBUG("Got command line argument %s from lua", argv[argc - 1]);
696       }
697     }
698     argv[argc--] = NULL;
699
700     /* Initialize the MSG core */
701     MSG_global_init(&argc, argv);
702     XBT_DEBUG("Still %d arguments on command line", argc); // FIXME: update the lua's arg table to reflect the changes from SimGrid
703   }
704
705   /* Keep the context mechanism informed of our lua world today */
706   sglua_maestro_state = L;
707
708   /* initialize access to my tables by children Lua states */
709   lua_newtable(L);
710   lua_setfield(L, LUA_REGISTRYINDEX, "simgrid.maestro_tables");
711
712   register_c_functions(L);
713
714   return 1;
715 }
716
717 /**
718  * @brief Returns whether a Lua state is the maestro state.
719  * @param L a Lua state
720  * @return true if this is maestro
721  */
722 int sglua_is_maestro(lua_State* L) {
723   return L == sglua_maestro_state;
724 }
725
726 /**
727  * @brief Returns the maestro state.
728  * @return true the maestro Lua state
729  */
730 lua_State* sglua_get_maestro(void) {
731   return sglua_maestro_state;
732 }
733
734 /**
735  * Makes the appropriate Simgrid functions available to the Lua world.
736  * @param L a Lua world
737  */
738 void register_c_functions(lua_State *L) {
739
740   /* register the core C functions to lua */
741   luaL_register(L, "simgrid", simgrid_functions);
742
743   /* register the task methods to lua */
744   luaL_openlib(L, TASK_MODULE_NAME, task_functions, 0);   // create methods table, add it to the globals
745   luaL_newmetatable(L, TASK_MODULE_NAME);       // create metatable for Task, add it to the Lua registry
746   luaL_openlib(L, 0, task_meta, 0);     // fill metatable
747   lua_pushliteral(L, "__index");
748   lua_pushvalue(L, -3);         // dup methods table
749   lua_rawset(L, -3);            // metatable.__index = methods
750   lua_pushliteral(L, "__metatable");
751   lua_pushvalue(L, -3);         // dup methods table
752   lua_rawset(L, -3);            // hide metatable:metatable.__metatable = methods
753   lua_pop(L, 1);                // drop metatable
754
755   /* register the hosts methods to lua */
756   luaL_openlib(L, HOST_MODULE_NAME, host_functions, 0);
757   luaL_newmetatable(L, HOST_MODULE_NAME);
758   luaL_openlib(L, 0, host_meta, 0);
759   lua_pushliteral(L, "__index");
760   lua_pushvalue(L, -3);
761   lua_rawset(L, -3);
762   lua_pushliteral(L, "__metatable");
763   lua_pushvalue(L, -3);
764   lua_rawset(L, -3);
765   lua_pop(L, 1);
766
767   /* register the platform methods to lua */
768   luaL_openlib(L, PLATF_MODULE_NAME, platf_functions, 0);
769   luaL_newmetatable(L, PLATF_MODULE_NAME);
770   lua_pop(L, 1);
771 }