1 #include "interpreter.h"
2 #include "expr.h"
3 
4 #include <geogram/lua/lua_io.h>
5 #include <geogram/basic/logger.h>
6 
7 extern "C" {
8 #include <geogram/third_party/lua/lauxlib.h>
9 #include <geogram/third_party/lua/lualib.h>
10 }
11 
12 
13 namespace GEO {
14 
lua_isexpr(lua_State * L,int index)15     bool lua_isexpr(lua_State* L, int index) {
16 	if(lua_islightuserdata(L,index)) {
17 	    return false;
18 	}
19 	if(!lua_isuserdata(L,index)) {
20 	    return false;
21 	}
22 	lua_getmetatable(L,index);
23 	lua_getfield(L,LUA_REGISTRYINDEX,"expr_vtbl");
24 	bool result = (lua_compare(L, -1, -2, LUA_OPEQ) != 0);
25 	lua_pop(L,2);
26 	return result;
27     }
28 
29     struct ExprRef {
30 	Expr* expr;
31     };
32 
lua_pushexpr(lua_State * L,Expr * expr)33     void lua_pushexpr(lua_State* L, Expr* expr) {
34 	if(expr == nullptr) {
35 	    lua_pushnil(L);
36 	    return;
37 	}
38 	void* p = lua_newuserdata(L,sizeof(ExprRef));
39 	ExprRef* ER = static_cast<ExprRef*>(p);
40 	ER->expr = expr;
41 	ER->expr->ref();
42 	lua_getfield(L,LUA_REGISTRYINDEX,"expr_vtbl");
43 	lua_setmetatable(L,-2);
44     }
45 
lua_toexpr(lua_State * L,int index)46     Expr* lua_toexpr(lua_State* L, int index) {
47 	geo_assert(lua_isexpr(L,index));
48 	return static_cast<ExprRef*>(
49 	    lua_touserdata(L,index)
50 	)->expr;
51     }
52 
lua_convert_toexpr(lua_State * L,int index)53     Expr* lua_convert_toexpr(lua_State* L, int index) {
54 	if(lua_isexpr(L,index)) {
55 	    return lua_toexpr(L,index);
56 	}
57 	if(lua_isnumber(L,index)) {
58 	    return new Constant(lua_tonumber(L,index));
59 	}
60 	return nullptr;
61     }
62 
expr_gc(lua_State * L)63     int expr_gc(lua_State* L) {
64 	geo_debug_assert(lua_isexpr(L,1));
65 	ExprRef* ER = static_cast<ExprRef*>(
66 	    lua_touserdata(L,1)
67 	);
68 	if(ER->expr != nullptr) {
69 	    ER->expr->unref();
70 	}
71 	ER->expr = nullptr;
72 	return 0;
73     }
74 
expr_add(lua_State * L)75     int expr_add(lua_State* L) {
76 	Expr* op1 = lua_convert_toexpr(L,-2);
77 	Expr* op2 = lua_convert_toexpr(L,-1);
78 	if(op1 == nullptr || op2 == nullptr) {
79 	    Logger::err("PCK") << "+: invalid operand types"
80 			       << std::endl;
81 	    return 0;
82 	}
83 	SmartPointer<Sum> result = new Sum;
84 	result->add_term(op1);
85 	result->add_term(op2);
86 	if(result->nb_terms() == 1) {
87 	    lua_pushexpr(L,result->ith_term(0));
88 	} else {
89 	    lua_pushexpr(L,result);
90 	}
91 	return 1;
92     }
93 
expr_sub(lua_State * L)94     int expr_sub(lua_State* L) {
95 	Expr* op1 = lua_convert_toexpr(L,-2);
96 	Expr* op2 = lua_convert_toexpr(L,-1);
97 	if(op1 == nullptr || op2 == nullptr) {
98 	    Logger::err("PCK") << "-: invalid operand types"
99 			       << std::endl;
100 	    return 0;
101 	}
102 
103 	SmartPointer<Sum> result = new Sum;
104 	result->add_term(op1);
105 
106 	Constant* cop2 = dynamic_cast<Constant*>(op2);
107 	if(cop2 != nullptr) {
108 	    result->add_term(new Constant(-cop2->value()));
109 	} else {
110 	    Product* mop2 = new Product;
111 	    mop2->mult_factor(new Constant(-1.0));
112 	    mop2->mult_factor(op2);
113 	    result->add_term(mop2);
114 	}
115 
116 	if(result->nb_terms() == 1) {
117 	    lua_pushexpr(L,result->ith_term(0));
118 	} else {
119 	    lua_pushexpr(L,result);
120 	}
121 	return 1;
122     }
123 
expr_mul(lua_State * L)124     int expr_mul(lua_State* L) {
125 	Expr* op1 = lua_convert_toexpr(L,-2);
126 	Expr* op2 = lua_convert_toexpr(L,-1);
127 	if(op1 == nullptr || op2 == nullptr) {
128 	    Logger::err("PCK") << "+: invalid operand types"
129 			       << std::endl;
130 	    return 0;
131 	}
132 	SmartPointer<Product> result = new Product;
133 	result->mult_factor(op1);
134 	result->mult_factor(op2);
135 
136 	if(result->nb_factors() == 1) {
137 	    lua_pushexpr(L,result->ith_factor(0));
138 	} else {
139 	    lua_pushexpr(L,result);
140 	}
141 	return 1;
142     }
143 
expr_pow(lua_State * L)144     int expr_pow(lua_State* L) {
145 	Expr* arg = lua_convert_toexpr(L,-2);
146 	lua_Integer expo = -1;
147 	if(lua_isinteger(L,-1)) {
148 	    expo = lua_tointeger(L,-1);
149 	}
150 	if(arg == nullptr || expo == -1) {
151 	    Logger::err("PCK") << "^: invalid operand types"
152 			       << std::endl;
153 	    return 0;
154 	}
155 	lua_pushexpr(L, new Pow(arg, index_t(expo)));
156 	return 1;
157     }
158 
expr_index(lua_State * L)159     int expr_index(lua_State* L) {
160 	Expr* arg = lua_convert_toexpr(L,-2);
161 	lua_Integer index = -1;
162 	const char* name = nullptr;
163 	if(lua_isinteger(L,-1)) {
164 	    index = lua_tointeger(L,-1);
165 	} else if(lua_isstring(L,-1)) {
166 	    name = lua_tostring(L,-1);
167 	}
168 	if(
169 	    arg == nullptr ||
170 	    arg->type() != Expr::VECTOR ||
171 	    (index == -1 && name == nullptr)
172 	) {
173 	    Logger::err("PCK") << "index: invalid operand types"
174 			       << std::endl;
175 	    return 0;
176 	}
177 	if(index == -1) {
178 	           if(!strcmp(name,"x") || !strcmp(name,"r")) {
179 	      index = 0;
180 	    } else if(!strcmp(name,"y") || !strcmp(name,"g")) {
181 	      index = 1;
182 	    } else if(!strcmp(name,"z") || !strcmp(name,"b")) {
183 	      index = 2;
184 	    } else if(!strcmp(name,"w") || !strcmp(name,"a")) {
185 	      index = 3;
186 	    }
187 	}
188 	if(index < 0 || index >= arg->dim()) {
189 	    Logger::err("PCK") << "index: invalid index"
190 			       << std::endl;
191 	    return 0;
192 	}
193 	lua_pushexpr(L,new VectorComponent(arg, index_t(index)));
194 	return 1;
195     }
196 
expr_len(lua_State * L)197     int expr_len(lua_State* L) {
198 	Expr* arg = lua_convert_toexpr(L,-1);
199 	if(arg == nullptr) {
200 	    Logger::err("PCK") << "len: invalid operand types"
201 			       << std::endl;
202 	    return 0;
203 	}
204 	lua_pushinteger(L,arg->dim());
205 	return 1;
206     }
207 
PCK_print(lua_State * L)208     int PCK_print(lua_State* L) {
209 	if(lua_isexpr(L,1)) {
210 	    Expr* expr = lua_toexpr(L,1);
211 	    if(expr == nullptr) {
212 		Logger::out("LUA") << "nil expr" << std::endl;
213 	    } else {
214 		Logger::out("LUA") << expr->to_string() << std::endl;
215 	    }
216 	} else {
217 	    Logger::out("LUA") << "Not an expr" << std::endl;
218 	}
219 	return 0;
220     }
221 
PCK_scalar(lua_State * L)222     int PCK_scalar(lua_State* L) {
223 	lua_pushexpr(L, new ScalarVar);
224 	return 1;
225     }
226 
PCK_vec(lua_State * L)227     int PCK_vec(lua_State* L) {
228 	lua_pushexpr(L, new VectorVar);
229 	return 1;
230     }
231 
PCK_vec2(lua_State * L)232     int PCK_vec2(lua_State* L) {
233 	lua_pushexpr(L, new VectorVar(2));
234 	return 1;
235     }
236 
PCK_vec3(lua_State * L)237     int PCK_vec3(lua_State* L) {
238 	lua_pushexpr(L, new VectorVar(3));
239 	return 1;
240     }
241 
PCK_vec4(lua_State * L)242     int PCK_vec4(lua_State* L) {
243 	lua_pushexpr(L, new VectorVar(4));
244 	return 1;
245     }
246 
PCK_Sign(lua_State * L)247     int PCK_Sign(lua_State* L) {
248 	lua_pushexpr(L, new SignVar);
249 	return 1;
250     }
251 
PCK_set_default_dim(lua_State * L)252     int PCK_set_default_dim(lua_State* L) {
253 	if(lua_gettop(L) != 1) {
254 	    Logger::err("PCK") << "set_defaut_dim(): invalid number of operants"
255 			       << std::endl;
256 	    return 0;
257 	}
258 	if(!lua_isinteger(L,-1)) {
259 	    Logger::err("PCK") << "set_defaut_dim(): invalid operand types"
260 			       << std::endl;
261 	}
262 	lua_Integer dim = lua_tointeger(L,-1);
263 	if(dim < 1) {
264 	    Logger::err("PCK") << "set_defaut_dim(): invalid operand value"
265 			       << std::endl;
266 	}
267 	VectorVar::set_default_dim(index_t(dim));
268 	return 0;
269     }
270 }
271 
272 namespace GEO {
273 
274     Interpreter* Interpreter::instance_ = nullptr;
275 
Interpreter()276     Interpreter::Interpreter() {
277 	geo_assert(instance_ == nullptr);
278 	instance_ = this;
279 
280 	lua_state_ = luaL_newstate();
281 	luaL_openlibs(lua_state_);
282 	init_lua_io(lua_state_);
283 
284 	// Expr member functions
285 	lua_newtable(lua_state_);
286 
287 	lua_pushliteral(lua_state_,"__gc");
288 	lua_pushcfunction(lua_state_,expr_gc);
289 	lua_settable(lua_state_,-3);
290 
291 	lua_pushliteral(lua_state_,"__add");
292 	lua_pushcfunction(lua_state_,expr_add);
293 	lua_settable(lua_state_,-3);
294 
295 	lua_pushliteral(lua_state_,"__sub");
296 	lua_pushcfunction(lua_state_,expr_sub);
297 	lua_settable(lua_state_,-3);
298 
299 	lua_pushliteral(lua_state_,"__mul");
300 	lua_pushcfunction(lua_state_,expr_mul);
301 	lua_settable(lua_state_,-3);
302 
303 	lua_pushliteral(lua_state_,"__pow");
304 	lua_pushcfunction(lua_state_,expr_pow);
305 	lua_settable(lua_state_,-3);
306 
307 	lua_pushliteral(lua_state_,"__index");
308 	lua_pushcfunction(lua_state_,expr_index);
309 	lua_settable(lua_state_,-3);
310 
311 	lua_pushliteral(lua_state_,"__len");
312 	lua_pushcfunction(lua_state_,expr_len);
313 	lua_settable(lua_state_,-3);
314 
315 	lua_setfield(lua_state_, LUA_REGISTRYINDEX, "expr_vtbl");
316 
317 	/**********************************************************/
318 
319 	// global functions
320 
321 	lua_pushcfunction(lua_state_,PCK_scalar);
322 	lua_setglobal(lua_state_, "scalar");
323 
324 	lua_pushcfunction(lua_state_,PCK_vec);
325 	lua_setglobal(lua_state_, "vec");
326 
327 	lua_pushcfunction(lua_state_,PCK_vec2);
328 	lua_setglobal(lua_state_, "vec2");
329 
330 	lua_pushcfunction(lua_state_,PCK_vec3);
331 	lua_setglobal(lua_state_, "vec3");
332 
333 	lua_pushcfunction(lua_state_,PCK_vec4);
334 	lua_setglobal(lua_state_, "vec4");
335 
336 	lua_pushcfunction(lua_state_,PCK_Sign);
337 	lua_setglobal(lua_state_, "Sign");
338 
339 
340 	/**********************************************************/
341 
342 	// PCK functions
343 	lua_newtable(lua_state_);
344 
345 	lua_pushliteral(lua_state_,"print");
346 	lua_pushcfunction(lua_state_,PCK_print);
347 	lua_settable(lua_state_,-3);
348 
349 	lua_pushliteral(lua_state_,"set_default_dim");
350 	lua_pushcfunction(lua_state_,PCK_set_default_dim);
351 	lua_settable(lua_state_,-3);
352 
353 
354 	lua_setglobal(lua_state_, "PCK");
355     }
356 
~Interpreter()357     Interpreter::~Interpreter() {
358 	lua_close(lua_state_);
359 	instance_ = nullptr;
360     }
361 
run_file(const std::string & filename)362     void Interpreter::run_file(const std::string& filename) {
363 	if(luaL_dofile(lua_state_,filename.c_str())) {
364 	    const char* msg = lua_tostring(lua_state_,-1);
365 	    Logger::err("Lua") << msg << std::endl;
366 	}
367     }
368 
369 }
370 
371 
372