LazyTable.cc
1 /*
2  * MoMEMta: a modular implementation of the Matrix Element Method
3  * Copyright (C) 2016 Universite catholique de Louvain (UCL), Belgium
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <lua/LazyTable.h>
20 
21 #include <cassert>
22 
23 #include <momemta/Logging.h>
24 #include <momemta/Unused.h>
25 
26 #include <lua/utils.h>
27 
28 namespace lua {
29 
30 LazyTableField::LazyTableField(lua_State *L, const std::string& table_name, const std::string& key) :
31  Lazy(L) {
32  this->table_name = table_name;
33  this->key = key;
34 }
35 
36 void LazyTableField::ensure_created() {
37  // Push the table on the stack. Stack +1
38  int type = lua_getglobal(L, table_name.c_str());
39  // Discard the result. Stack -1
40  lua_pop(L, 1);
41 
42  // Already existing
43  if (type != LUA_TNIL)
44  return;
45 
46  // Create a new table. Stack +1
47  lua_newtable(L);
48  // Set it global. Stack -1
49  lua_setglobal(L, table_name.c_str());
50 }
51 
52 momemta::any LazyTableField::operator()() const {
53  LOG(trace) << "[LazyTableField::operator()] >> stack size = " << lua_gettop(L);
54 
55  // Push the table on the stack. Stack +1
56  lua_getglobal(L, table_name.c_str());
57 
58  // Push the requested field from the table to the stack. Stack +1
59  lua_getfield(L, -1, key.c_str());
60 
61  momemta::any value;
62  bool lazy = false;
63  std::tie(value, lazy) = to_any(L, -1);
64  assert(!lazy);
65 
66  // Pop the field and the table from the stack. Stack -2
67  lua_pop(L, 2);
68 
69  LOG(trace) << "[LazyTableField::operator()] << stack size = " << lua_gettop(L);
70 
71  return value;
72 }
73 
74 void LazyTableField::set(const momemta::any& value) {
75  LOG(trace) << "[LazyTableField::set] >> stack size = " << lua_gettop(L);
76 
77  // Push the table on the stack. Stack +1
78  lua_getglobal(L, table_name.c_str());
79 
80  // Push the value to the stack. Stack +1
81  lua::push_any(L, value);
82 
83  // Pop the requested field from the stack and assign it to the table. Stack -1
84  lua_setfield(L, -2, key.c_str());
85 
86  // Pop the table from the stack. Stack -1
87  lua_pop(L, 1);
88 
89  LOG(trace) << "[LazyTableField::set] << stack size = " << lua_gettop(L);
90 }
91 
92 LazyTable::LazyTable(std::shared_ptr<lua_State> L, const std::string& name):
93  ParameterSet("table", name) {
94  m_lua_state = L;
95 }
96 
97 bool LazyTable::lazy() const {
98  return true;
99 }
100 
101 void LazyTable::create(const std::string& name, const momemta::any& value) {
102 
103  lua::LazyTableField lazyField = lua::LazyTableField(m_lua_state.get(), getModuleName(), name);
104  lazyField.ensure_created();
105  lazyField.set(value);
106 
107  m_set.emplace(name, Element(lazyField, true));
108 }
109 
110 void LazyTable::setInternal(const std::string& name, Element& element, const momemta::any& value) {
111 
112  // We know that this set is not frozen, so *all* the items in the map
113  // are actually lazy reference to lua table values.
114  // Instead of editing directly the value, we edit the value of the global table
115  // directly in lua user-space
116  UNUSED(name);
117 
118  assert(element.lazy);
119  assert(element.value.type() == typeid(lua::LazyTableField));
120 
121  momemta::any_cast<lua::LazyTableField&>(element.value).set(value);
122 }
123 
124 void LazyTable::freeze() {
125  ParameterSet::freeze();
126 
127  // Release lua_State. We don't need it anymore
128  m_lua_state.reset();
129 }
130 
131 LazyTable* LazyTable::clone() const {
132  return new LazyTable(*this);
133 }
134 
135 
136 }
A specialization of ParameterSet for lazy loading of lua tables.
Definition: LazyTable.h:62
Lazy table field in lua (delayed table access)
Definition: LazyTable.h:35
A small wrapper around a momemta::any value.
Definition: ParameterSet.h:259
Type type(lua_State *L, int index)
Extract the type of a lua value.
Definition: utils.cc:81
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.
Definition: utils.cc:271
A class encapsulating a lua table.
Definition: ParameterSet.h:82
void set(const momemta::any &value)
Replace the value of the table field by a new one.
Definition: LazyTable.cc:74
std::pair< momemta::any, bool > to_any(lua_State *L, int index)
Convert a lua type to momemta::any.
Definition: utils.cc:191
void ensure_created()
Ensure the global table referenced by this struct exist. If not, create it.
Definition: LazyTable.cc:36
Utility functions related to lua configuration file parsing.
Definition: Path.h:31