Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Make the Lua API respect coherent naming conventions
[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_gc(lua_State * L)
459 {
460   m_host_t ht = sglua_checkhost(L, -1);
461   if (ht)
462     ht = NULL;
463   return 0;
464 }
465
466 static int l_host_tostring(lua_State * L)
467 {
468   lua_pushfstring(L, "Host :%p", lua_touserdata(L, 1));
469   return 1;
470 }
471
472 static const luaL_reg host_meta[] = {
473   {"__gc", l_host_gc},
474   {"__tostring", l_host_tostring},
475   {0, 0}
476 };
477
478 /*
479  * AS Methods
480  */
481 static const luaL_reg platf_functions[] = {
482     {"open", console_open},
483     {"close", console_close},
484     {"AS_open", console_AS_open},
485     {"AS_close", console_AS_close},
486     {"host_new", console_add_host},
487     {"link_new", console_add_link},
488     {"router_new", console_add_router},
489     {"route_new", console_add_route},
490     {NULL, NULL}
491 };
492
493 /*
494  * Environment related
495  */
496
497 /**
498  * @brief Runs a Lua function as a new simulated process.
499  * @param argc number of arguments of the function
500  * @param argv name of the Lua function and array of its arguments
501  * @return result of the function
502  */
503 static int run_lua_code(int argc, char **argv)
504 {
505   XBT_DEBUG("Run lua code %s", argv[0]);
506
507   lua_State *L = sglua_clone_maestro();
508   int res = 1;
509
510   /* start the function */
511   lua_getglobal(L, argv[0]);
512   xbt_assert(lua_isfunction(L, -1),
513               "The lua function %s does not seem to exist", argv[0]);
514
515   /* push arguments onto the stack */
516   int i;
517   for (i = 1; i < argc; i++)
518     lua_pushstring(L, argv[i]);
519
520   /* call the function */
521   _XBT_GNUC_UNUSED int err;
522   err = lua_pcall(L, argc - 1, 1, 0);
523   xbt_assert(err == 0, "error running function `%s': %s", argv[0],
524               lua_tostring(L, -1));
525
526   /* retrieve result */
527   if (lua_isnumber(L, -1)) {
528     res = lua_tonumber(L, -1);
529     lua_pop(L, 1);              /* pop returned value */
530   }
531
532   XBT_DEBUG("Execution of Lua code %s is over", (argv ? argv[0] : "(null)"));
533
534   return res;
535 }
536
537 static int launch_application(lua_State * L)
538 {
539   const char *file = luaL_checkstring(L, 1);
540   MSG_function_register_default(run_lua_code);
541   MSG_launch_application(file);
542   return 0;
543 }
544
545 static int create_environment(lua_State * L)
546 {
547   const char *file = luaL_checkstring(L, 1);
548   XBT_DEBUG("Loading environment file %s", file);
549   MSG_create_environment(file);
550   return 0;
551 }
552
553 static int debug(lua_State * L)
554 {
555   const char *str = luaL_checkstring(L, 1);
556   XBT_DEBUG("%s", str);
557   return 0;
558 }
559
560 static int info(lua_State * L)
561 {
562   const char *str = luaL_checkstring(L, 1);
563   XBT_INFO("%s", str);
564   return 0;
565 }
566
567 static int run(lua_State * L)
568 {
569   MSG_main();
570   return 0;
571 }
572
573 static int clean(lua_State * L)
574 {
575   MSG_clean();
576   return 0;
577 }
578
579 /*
580  * Bypass XML Parser (lua console)
581  */
582
583 /*
584  * Register platform for MSG
585  */
586 static int msg_register_platform(lua_State * L)
587 {
588   /* Tell Simgrid we dont wanna use its parser */
589   //surf_parse = console_parse_platform;
590   surf_parse_reset_callbacks();
591   MSG_create_environment(NULL);
592   return 0;
593 }
594
595 /*
596  * Register platform for Simdag
597  */
598
599 static int sd_register_platform(lua_State * L)
600 {
601   //surf_parse = console_parse_platform_wsL07;
602   surf_parse_reset_callbacks();
603   SD_create_environment(NULL);
604   return 0;
605 }
606
607 /*
608  * Register platform for gras
609  */
610 static int gras_register_platform(lua_State * L)
611 {
612   //surf_parse = console_parse_platform;
613   surf_parse_reset_callbacks();
614   gras_create_environment(NULL);
615   return 0;
616 }
617
618 /**
619  * Register applicaiton for MSG
620  */
621 static int msg_register_application(lua_State * L)
622 {
623   MSG_function_register_default(run_lua_code);
624   //surf_parse = console_parse_application;
625   MSG_launch_application(NULL);
626   return 0;
627 }
628
629 /*
630  * Register application for gras
631  */
632 static int gras_register_application(lua_State * L)
633 {
634   gras_function_register_default(run_lua_code);
635   //surf_parse = console_parse_application;
636   gras_launch_application(NULL);
637   return 0;
638 }
639
640 static const luaL_Reg simgrid_functions[] = {
641   {"create_environment", create_environment},
642   {"launch_application", launch_application},
643   {"debug", debug},
644   {"info", info},
645   {"run", run},
646   {"clean", clean},
647   /* short names */
648   {"platform", create_environment},
649   {"application", launch_application},
650   /* methods to bypass XML parser */
651   {"msg_register_platform", msg_register_platform},
652   {"sd_register_platform", sd_register_platform},
653   {"msg_register_application", msg_register_application},
654   {"gras_register_platform", gras_register_platform},
655   {"gras_register_application", gras_register_application},
656   /* gras sub generator method */
657   {"gras_set_process_function", gras_add_process_function},
658   {"gras_generate", gras_generate},
659   {NULL, NULL}
660 };
661
662 /* ********************************************************************************* */
663 /*                       module management functions                                 */
664 /* ********************************************************************************* */
665
666 #define LUA_MAX_ARGS_COUNT 10   /* maximum amount of arguments we can get from lua on command line */
667
668 int luaopen_simgrid(lua_State *L);     // Fuck gcc: we don't need that prototype
669
670 /**
671  * This function is called automatically by the Lua interpreter when some Lua code requires
672  * the "simgrid" module.
673  * @param L the Lua state
674  */
675 int luaopen_simgrid(lua_State *L)
676 {
677   XBT_DEBUG("luaopen_simgrid *****");
678
679   /* Get the command line arguments from the lua interpreter */
680   char **argv = malloc(sizeof(char *) * LUA_MAX_ARGS_COUNT);
681   int argc = 1;
682   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? */
683
684   lua_getglobal(L, "arg");
685   /* if arg is a null value, it means we use lua only as a script to init platform
686    * else it should be a table and then take arg in consideration
687    */
688   if (lua_istable(L, -1)) {
689     int done = 0;
690     while (!done) {
691       argc++;
692       lua_pushinteger(L, argc - 2);
693       lua_gettable(L, -2);
694       if (lua_isnil(L, -1)) {
695         done = 1;
696       } else {
697         xbt_assert(lua_isstring(L, -1),
698                     "argv[%d] got from lua is no string", argc - 1);
699         xbt_assert(argc < LUA_MAX_ARGS_COUNT,
700                     "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",
701                     __FILE__, LUA_MAX_ARGS_COUNT - 1);
702         argv[argc - 1] = (char *) luaL_checkstring(L, -1);
703         lua_pop(L, 1);
704         XBT_DEBUG("Got command line argument %s from lua", argv[argc - 1]);
705       }
706     }
707     argv[argc--] = NULL;
708
709     /* Initialize the MSG core */
710     MSG_global_init(&argc, argv);
711     XBT_DEBUG("Still %d arguments on command line", argc); // FIXME: update the lua's arg table to reflect the changes from SimGrid
712   }
713
714   /* Keep the context mechanism informed of our lua world today */
715   sglua_maestro_state = L;
716
717   /* initialize access to my tables by children Lua states */
718   lua_newtable(L);
719   lua_setfield(L, LUA_REGISTRYINDEX, "simgrid.maestro_tables");
720
721   register_c_functions(L);
722
723   return 1;
724 }
725
726 /**
727  * @brief Returns whether a Lua state is the maestro state.
728  * @param L a Lua state
729  * @return true if this is maestro
730  */
731 int sglua_is_maestro(lua_State* L) {
732   return L == sglua_maestro_state;
733 }
734
735 /**
736  * @brief Returns the maestro state.
737  * @return true the maestro Lua state
738  */
739 lua_State* sglua_get_maestro(void) {
740   return sglua_maestro_state;
741 }
742
743 /**
744  * Makes the appropriate Simgrid functions available to the Lua world.
745  * @param L a Lua world
746  */
747 void register_c_functions(lua_State *L) {
748
749   /* register the core C functions to lua */
750   luaL_register(L, "simgrid", simgrid_functions);
751
752   /* register the task methods to lua */
753   luaL_openlib(L, TASK_MODULE_NAME, task_functions, 0);   // create methods table, add it to the globals
754   luaL_newmetatable(L, TASK_MODULE_NAME);       // create metatable for Task, add it to the Lua registry
755   luaL_openlib(L, 0, task_meta, 0);     // fill metatable
756   lua_pushliteral(L, "__index");
757   lua_pushvalue(L, -3);         // dup methods table
758   lua_rawset(L, -3);            // metatable.__index = methods
759   lua_pushliteral(L, "__metatable");
760   lua_pushvalue(L, -3);         // dup methods table
761   lua_rawset(L, -3);            // hide metatable:metatable.__metatable = methods
762   lua_pop(L, 1);                // drop metatable
763
764   /* register the hosts methods to lua */
765   luaL_openlib(L, HOST_MODULE_NAME, host_functions, 0);
766   luaL_newmetatable(L, HOST_MODULE_NAME);
767   luaL_openlib(L, 0, host_meta, 0);
768   lua_pushliteral(L, "__index");
769   lua_pushvalue(L, -3);
770   lua_rawset(L, -3);
771   lua_pushliteral(L, "__metatable");
772   lua_pushvalue(L, -3);
773   lua_rawset(L, -3);
774   lua_pop(L, 1);
775
776   /* register the platform methods to lua */
777   luaL_openlib(L, PLATF_MODULE_NAME, platf_functions, 0);
778   luaL_newmetatable(L, PLATF_MODULE_NAME);
779   lua_pop(L, 1);
780 }