Lua API: Add wesnoth.compile_formula which returns a callable userdata
This commit is contained in:
parent
ac4479090f
commit
5bb6c30b05
5 changed files with 104 additions and 5 deletions
|
@ -4257,6 +4257,7 @@ game_lua_kernel::game_lua_kernel(CVideo * video, game_state & gs, play_controlle
|
|||
{ "add_known_unit", &intf_add_known_unit },
|
||||
{ "add_modification", &intf_add_modification },
|
||||
{ "advance_unit", &intf_advance_unit },
|
||||
{ "compile_formula", &lua_formula_bridge::intf_compile_formula},
|
||||
{ "copy_unit", &intf_copy_unit },
|
||||
{ "create_unit", &intf_create_unit },
|
||||
{ "debug", &intf_debug },
|
||||
|
@ -4455,6 +4456,9 @@ game_lua_kernel::game_lua_kernel(CVideo * video, game_state & gs, play_controlle
|
|||
lua_pushstring(L, "unit variables");
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
|
||||
// Create formula bridge metatables
|
||||
cmd_log_ << lua_formula_bridge::register_metatables(L);
|
||||
|
||||
// Create the vconfig metatable.
|
||||
cmd_log_ << lua_common::register_vconfig_metatable(L);
|
||||
|
|
|
@ -201,11 +201,14 @@ variant luaW_tofaivariant(lua_State* L, int i) {
|
|||
*/
|
||||
int lua_formula_bridge::intf_eval_formula(lua_State *L)
|
||||
{
|
||||
using namespace game_logic;
|
||||
if(!lua_isstring(L, 1)) {
|
||||
luaL_typerror(L, 1, "string");
|
||||
bool need_delete = false;
|
||||
fwrapper* form;
|
||||
if(luaW_hasmetatable(L, 1, formulaKey)) {
|
||||
form = static_cast<fwrapper*>(lua_touserdata(L, 1));
|
||||
} else {
|
||||
need_delete = true;
|
||||
form = new fwrapper(luaL_checkstring(L, 1));
|
||||
}
|
||||
const formula form(lua_tostring(L, 1));
|
||||
boost::shared_ptr<formula_callable> context, fallback;
|
||||
if(unit* u = luaW_tounit(L, 2)) {
|
||||
context.reset(new unit_callable(*u));
|
||||
|
@ -214,7 +217,75 @@ int lua_formula_bridge::intf_eval_formula(lua_State *L)
|
|||
} else {
|
||||
context.reset(new map_formula_callable);
|
||||
}
|
||||
variant result = form.evaluate(*context);
|
||||
variant result = form->evaluate(*context);
|
||||
luaW_pushfaivariant(L, result);
|
||||
if(need_delete) {
|
||||
delete form;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_formula_bridge::intf_compile_formula(lua_State* L)
|
||||
{
|
||||
if(!lua_isstring(L, 1)) {
|
||||
luaL_typerror(L, 1, "string");
|
||||
}
|
||||
new(lua_newuserdata(L, sizeof(fwrapper))) fwrapper(lua_tostring(L, 1));
|
||||
lua_pushlightuserdata(L, formulaKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_formula_bridge::fwrapper::fwrapper(const std::string& code, game_logic::function_symbol_table* functions)
|
||||
: formula_ptr(new formula(code, functions))
|
||||
{
|
||||
}
|
||||
|
||||
std::string lua_formula_bridge::fwrapper::str() const
|
||||
{
|
||||
if(formula_ptr) {
|
||||
return formula_ptr->str();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
variant lua_formula_bridge::fwrapper::evaluate(const formula_callable& variables, formula_debugger* fdb) const
|
||||
{
|
||||
if(formula_ptr) {
|
||||
return formula_ptr->evaluate(variables, fdb);
|
||||
}
|
||||
return variant();
|
||||
}
|
||||
|
||||
static int impl_formula_collect(lua_State* L)
|
||||
{
|
||||
lua_formula_bridge::fwrapper* form = static_cast<lua_formula_bridge::fwrapper*>(lua_touserdata(L, 1));
|
||||
form->~fwrapper();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int impl_formula_tostring(lua_State* L)
|
||||
{
|
||||
lua_formula_bridge::fwrapper* form = static_cast<lua_formula_bridge::fwrapper*>(lua_touserdata(L, 1));
|
||||
const std::string str = form->str();
|
||||
lua_pushlstring(L, str.c_str(), str.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string lua_formula_bridge::register_metatables(lua_State* L)
|
||||
{
|
||||
lua_pushlightuserdata(L, formulaKey);
|
||||
lua_createtable(L, 0, 4);
|
||||
lua_pushcfunction(L, impl_formula_collect);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
lua_pushcfunction(L, impl_formula_tostring);
|
||||
lua_setfield(L, -2, "__tostring");
|
||||
lua_pushcfunction(L, intf_eval_formula);
|
||||
lua_setfield(L, -2, "__call");
|
||||
lua_pushstring(L, "formula");
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
|
||||
return "Adding formula metatable...";
|
||||
}
|
||||
|
|
|
@ -14,11 +14,32 @@
|
|||
#ifndef LUA_FORMULA_BRIDGE_HPP_INCLUDED
|
||||
#define LUA_FORMULA_BRIDGE_HPP_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
struct lua_State;
|
||||
|
||||
class variant;
|
||||
namespace game_logic {
|
||||
class formula;
|
||||
class function_symbol_table;
|
||||
class formula_debugger;
|
||||
class formula_callable;
|
||||
}
|
||||
|
||||
namespace lua_formula_bridge {
|
||||
|
||||
int intf_eval_formula(lua_State*);
|
||||
int intf_compile_formula(lua_State*);
|
||||
std::string register_metatables(lua_State*);
|
||||
|
||||
class fwrapper {
|
||||
boost::shared_ptr<game_logic::formula> formula_ptr;
|
||||
public:
|
||||
fwrapper(const std::string& code, game_logic::function_symbol_table* functions = NULL);
|
||||
std::string str() const;
|
||||
variant evaluate(const game_logic::formula_callable& variables, game_logic::formula_debugger* fdb = NULL) const;
|
||||
};
|
||||
|
||||
} // end namespace lua_formula_bridge
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ static char const v_unitvarKey = 0;
|
|||
static char const v_ustatusKey = 0;
|
||||
static char const v_uattacksKey = 0;
|
||||
static char const v_uattackKey = 0;
|
||||
static char const v_formulaKey = 0;
|
||||
|
||||
|
||||
luatypekey const executeKey = static_cast<void *>(const_cast<char *>(&v_executeKey));
|
||||
|
@ -29,3 +30,4 @@ luatypekey const unitvarKey = static_cast<void *>(const_cast<char *>(&v_unitvarK
|
|||
luatypekey const ustatusKey = static_cast<void *>(const_cast<char *>(&v_ustatusKey));
|
||||
luatypekey const uattacksKey = static_cast<void *>(const_cast<char *>(&v_uattacksKey));
|
||||
luatypekey const uattackKey = static_cast<void *>(const_cast<char *>(&v_uattackKey));
|
||||
luatypekey const formulaKey = static_cast<void *>(const_cast<char *>(&v_formulaKey));
|
||||
|
|
|
@ -25,5 +25,6 @@ extern luatypekey const unitvarKey;
|
|||
extern luatypekey const ustatusKey;
|
||||
extern luatypekey const uattacksKey;
|
||||
extern luatypekey const uattackKey;
|
||||
extern luatypekey const formulaKey;
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue