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