19 #include <lua/utils.h> 24 #include <momemta/InputTag.h> 25 #include <momemta/ILuaCallback.h> 26 #include <momemta/Logging.h> 27 #include <momemta/ModuleRegistry.h> 28 #include <momemta/ParameterSet.h> 29 #include <momemta/Utils.h> 31 #include <LibraryManager.h> 32 #include <lua/ParameterSetParser.h> 37 extern void execute_embed_lua_code(lua_State*);
41 Lazy::Lazy(lua_State* L) {
46 auto absolute_index =
get_index(L, index);
49 lua_pushvalue(L, absolute_index);
52 ref_index = luaL_ref(L, LUA_REGISTRYINDEX);
57 LOG(trace) <<
"[LazyFunction::operator()] >> stack size = " << lua_gettop(
L);
63 auto result = lua_pcall(
L, 0, 1, 0);
64 if (result != LUA_OK) {
65 std::string error = lua_tostring(
L, -1);
66 LOG(fatal) <<
"Fail to call lua anonymous function. Return value is " << result <<
". Error message: " << error;
71 std::tie(value, lazy) =
to_any(
L, -1);
76 LOG(trace) <<
"[LazyFunction::operator()] << stack size = " << lua_gettop(
L);
82 int t = lua_type(L, index);
90 std::string value = lua_tostring(L, index);
98 if (lua_isinteger(L, index))
117 return (index < 0) ? lua_gettop(L) + index + 1 : index;
127 LOG(trace) <<
"[lua_is_array] >> stack size = " << lua_gettop(L);
129 size_t table_index =
get_index(L, index);
131 if (lua_type(L, table_index) != LUA_TTABLE)
137 while (lua_next(L, table_index) != 0) {
138 if (lua_type(L, -2) != LUA_TNUMBER) {
140 LOG(trace) <<
"[lua_is_array] << stack size = " << lua_gettop(L);
149 LOG(trace) <<
"[lua_is_array] << stack size = " << lua_gettop(L);
160 size_t absolute_index =
get_index(L, index);
162 if (lua_type(L, absolute_index) != LUA_TTABLE)
168 while (lua_next(L, absolute_index) != 0) {
170 result =
type(L, -1);
176 else if ((result ==
REAL) && (entry_type ==
INTEGER))
178 else if (result != entry_type) {
191 std::pair<momemta::any, bool>
to_any(lua_State*
L,
int index) {
193 LOG(trace) <<
"[to_any] >> stack size = " << lua_gettop(L);
194 size_t absolute_index =
get_index(L, index);
199 auto type = lua_type(L, absolute_index);
202 if (lua_isinteger(L, absolute_index)) {
203 int64_t number = lua_tointeger(L, absolute_index);
206 double number = lua_tonumber(L, absolute_index);
212 bool value = lua_toboolean(L, absolute_index);
217 std::string value = lua_tostring(L, absolute_index);
227 LOG(trace) <<
"[to_any::table] >> stack size = " << lua_gettop(L);
233 result =
to_vector(L, absolute_index, type);
243 LOG(trace) <<
"[to_any::table] << stack size = " << lua_gettop(L);
246 case LUA_TFUNCTION: {
247 LOG(trace) <<
"[to_any::function] >> stack size = " << lua_gettop(L);
252 LOG(trace) <<
"[to_any::function] << stack size = " << lua_gettop(L);
255 case LUA_TUSERDATA: {
261 LOG(fatal) <<
"Unsupported lua type: " << lua_type(L, absolute_index);
266 LOG(trace) <<
"[to_any] << final type = " << demangle(result.type().name());
267 LOG(trace) <<
"[to_any] << stack size = " << lua_gettop(L);
268 return {result, lazy};
272 LOG(trace) <<
"[push_any] >> stack size = " << lua_gettop(L);
274 if (value.type() ==
typeid(int64_t)) {
275 int64_t v = momemta::any_cast<int64_t>(value);
276 lua_pushinteger(L, v);
277 }
else if (value.type() ==
typeid(double)) {
278 double v = momemta::any_cast<
double>(value);
279 lua_pushnumber(L, v);
280 }
else if (value.type() ==
typeid(bool)) {
281 bool v = momemta::any_cast<
bool>(value);
282 lua_pushboolean(L, v);
283 }
else if (value.type() ==
typeid(std::string)) {
284 auto v = momemta::any_cast<std::string>(value);
285 lua_pushstring(L, v.c_str());
286 }
else if (value.type() ==
typeid(
InputTag)) {
287 auto v = momemta::any_cast<
InputTag>(value).toString();
288 lua_pushstring(L, v.c_str());
290 LOG(fatal) <<
"Unsupported C++ value: " << demangle(value.type().name());
294 LOG(trace) <<
"[push_any] << stack size = " << lua_gettop(L);
300 return to_vectorT<bool>(
L, index);
303 return to_vectorT<std::string>(
L, index);
306 return to_vectorT<int64_t>(
L, index);
309 return to_vectorT<double>(
L, index);
312 return to_vectorT<InputTag>(
L, index);
315 return to_vectorT<ParameterSet>(
L, index);
326 if (value.type() ==
typeid(int64_t))
327 return static_cast<double>(momemta::any_cast<int64_t>(value));
329 return momemta::any_cast<
double>(value);
333 lua_getmetatable(L, 1);
334 lua_getfield(L, -1,
"__type");
336 const char* module_type = luaL_checkstring(L, -1);
337 const char* module_name = luaL_checkstring(L, 2);
344 static std::regex name_regex(
"[a-zA-Z][a-zA-Z0-9_]*");
346 if (! std::regex_match(module_name, name_regex)) {
347 luaL_error(L,
"invalid module name '%s': valid format is [a-zA-Z][a-zA-Z0-9_]*", module_name);
350 lua_getfield(L, -1,
"__ptr");
351 void* cfg_ptr = lua_touserdata(L, -1);
362 lua_pushstring(L,
"@name");
363 lua_pushstring(L, module_name);
366 lua_pushstring(L,
"@type");
367 lua_pushstring(L, module_type);
377 momemta::ModuleList modules;
380 for (
const auto& module: modules) {
381 const char* module_name = module.name.c_str();
383 int type = lua_getglobal(L, module_name);
385 if (type != LUA_TNIL) {
393 std::string module_metatable = module.name +
"_mt";
396 luaL_newmetatable(L, module_metatable.c_str());
398 lua_pushstring(L, module_name);
399 lua_setfield(L, -2,
"__type");
401 lua_pushlightuserdata(L, ptr);
402 lua_setfield(L, -2,
"__ptr");
407 const luaL_Reg l[] = {
411 luaL_setfuncs(L, l, 0);
413 lua_setmetatable(L, -2);
416 lua_setglobal(L, module_name);
418 LOG(trace) <<
"Registered new lua global variable '" << module_name <<
"'";
423 int n = lua_gettop(L);
425 luaL_error(L,
"invalid number of arguments: 1 expected, got %d", n);
428 void* cfg_ptr = lua_touserdata(L, lua_upvalueindex(1));
430 const char *path = luaL_checkstring(L, 1);
431 LibraryManager::get().registerLibrary(path);
439 int n = lua_gettop(L);
441 luaL_error(L,
"invalid number of arguments: 1 expected, got %d", n);
444 std::string parameter_name = luaL_checkstring(L, 1);
449 std::string code =
"return function() return parameters['" + parameter_name +
"'] end";
450 luaL_dostring(L, code.c_str());
455 int set_final_module(lua_State*
L) {
456 int n = lua_gettop(L);
458 luaL_error(L,
"invalid number of arguments: at least one expected, got 0");
461 void* cfg_ptr = lua_touserdata(L, lua_upvalueindex(1));
464 for(
size_t i = 1; i <= size_t(n); i++) {
465 std::string input_tag = luaL_checkstring(L, i);
467 luaL_error(L,
"'%s' is not a valid InputTag", input_tag.c_str());
475 int add_integration_dimension(lua_State* L) {
476 int n = lua_gettop(L);
478 luaL_error(L,
"invalid number of arguments: 0 expected, got %d", n);
482 int64_t cuba_index = lua_tonumber(L, lua_upvalueindex(1));
483 lua_pushnumber(L, cuba_index + 1);
484 lua_replace(L, lua_upvalueindex(1));
486 std::string index_tag =
"cuba::ps_points/";
487 index_tag += std::to_string(cuba_index);
493 void* cfg_ptr = lua_touserdata(L, lua_upvalueindex(2));
509 int n = lua_gettop(L);
511 luaL_error(L,
"invalid number of arguments: 1 expected, got %d", n);
514 std::string input_name = luaL_checkstring(L, 1);
516 void* cfg_ptr = lua_touserdata(L, lua_upvalueindex(1));
525 lua_pushlightuserdata(L, ptr);
527 lua_setglobal(L,
"load_modules");
529 lua_pushlightuserdata(L, ptr);
531 lua_setglobal(L,
"parameter");
535 lua_pushnumber(L, 1);
536 lua_pushlightuserdata(L, ptr);
537 lua_pushcclosure(L, add_integration_dimension, 2);
538 lua_setglobal(L,
"add_dimension");
541 lua_pushlightuserdata(L, ptr);
542 lua_pushcclosure(L, set_final_module, 1);
543 lua_setglobal(L,
"integrand");
546 lua_pushlightuserdata(L, ptr);
548 lua_setglobal(L,
"momemta_declare_input");
556 std::shared_ptr<lua_State>
L(luaL_newstate(), lua_close);
557 luaL_openlibs(L.get());
567 execute_embed_lua_code(L.get());
573 for (
const auto&
parameter: parameters.getNames()) {
574 LOG(debug) <<
"Injecting parameter " <<
parameter;
581 std::vector<std::string> dump_stack(lua_State *L) {
582 std::vector<std::string> stack;
583 for (
int i = 1; i < lua_gettop(L) + 1; i++) {
584 if (lua_isnumber(L, i)) {
585 stack.push_back(
"number : " + std::to_string(lua_tonumber(L, i)));
586 }
else if (lua_isstring(L, i)) {
587 stack.push_back(std::string(
"string : ") + std::string(luaL_checkstring(L, i)));
588 }
else if (lua_istable(L, i)) {
589 stack.push_back(
"table");
590 }
else if (lua_iscfunction(L, i)) {
591 stack.push_back(
"cfunction");
592 }
else if (lua_isfunction(L, i)) {
593 stack.push_back(
"function");
594 }
else if (lua_isboolean(L, i)) {
595 if (lua_toboolean(L, i) != 0)
596 stack.push_back(
"boolean: true");
598 stack.push_back(
"boolean: false");
599 }
else if (lua_isuserdata(L, i)) {
600 stack.push_back(
"userdata");
601 }
else if (lua_isnil(L, i)) {
602 stack.push_back(
"nil");
603 }
else if (lua_islightuserdata(L, i)) {
604 stack.push_back(
"lightuserdata");
611 void print_stack(lua_State* L) {
612 auto stack = dump_stack(L);
614 LOG(debug) <<
"Stack has " << stack.size() <<
" elements: ";
615 for (
const auto& e: stack) {
616 LOG(debug) <<
" #" << index++ <<
": " << e;
virtual void onModuleDeclared(const std::string &type, const std::string &name)=0
A module is declared in the configuration file.
Notification callback used for communication between the lua file and MoMEMta.
LazyFunction(lua_State *L, int index)
Bind a anonymous lua function.
size_t get_index(lua_State *L, int index)
Convert a negative lua stack index to an absolute index.
void setup_hooks(lua_State *L, void *ptr)
Register all C function in the lua userspace.
std::shared_ptr< lua_State > init_runtime(ILuaCallback *callback)
Initialize the lua runtime.
Lua binding of C++ Path class.
Type lua_array_unique_type(lua_State *L, int index)
Check if a lua table contains only value from the same type.
Type type(lua_State *L, int index)
Extract the type of a lua value.
int load_modules(lua_State *L)
Hook for the load_modules lua function. The stack must have one element:
int declare_input(lua_State *L)
The configuration file declared a new input.
int lua_is_array(lua_State *L, int index)
Check if a lua table is an array.
static ModuleRegistry & get()
A singleton available at startup.
static void parse(ParameterSet &p, lua_State *L, int index)
Convert a lua table to a ParameterSet.
Type
List of all supported lua types.
int ref_index
The reference index where the anonymous function is stored.
lua_State * L
The global lua state. This state must be valid for as long as this instance.
momemta::any to_vector(lua_State *L, int index, Type type)
Convert a lua array to a typed vector, encapsulated into a momemta::any.
void register_modules(lua_State *L, void *ptr)
Register modules in lua userspace.
void push_any(lua_State *L, const momemta::any &value)
Convert a momemta::any to a lua type, and push it to the top of the stack.
Generic functions to deal with custom lua types.
Lazy value in lua (delayed evaluation)
A class encapsulating a lua table.
int module_table_newindex(lua_State *L)
Hook for the metatable __newindex of the module's table.
virtual momemta::any operator()() const override
Evaluate the anonymous function.
void path_register(lua_State *L, void *ptr)
Register Path into lua runtime.
virtual void addIntegrationDimension()=0
A new integration dimension is requested in the configuration file.
< Thrown if the configuration file is not valid
virtual void onNewInputDeclared(const std::string &name)=0
The configuration file declared a new input.
momemta::any get_custom_type_ptr(lua_State *L, int index)
Convert a lua custom table to a momemta::any value.
virtual void onIntegrandDeclared(const InputTag &tag)=0
The integrand was defined in the configuration file.
void exportList(bool ignore_internal, ModuleList &list) const
int parameter(lua_State *L)
Hook for the parameter lua function. This function accepts one argument:
std::pair< momemta::any, bool > to_any(lua_State *L, int index)
Convert a lua type to momemta::any.
void inject_parameters(lua_State *L, const ParameterSet ¶meters)
Inject parameters into the current lua state.
const momemta::any & rawGet(const std::string &name) const
Utility functions related to lua configuration file parsing.