Move name generator and formula API to base Lua kernel

This commit is contained in:
Celtic Minstrel 2016-07-12 09:13:45 -04:00
parent 3c96dbc145
commit c39af95a44
4 changed files with 101 additions and 96 deletions

View file

@ -74,7 +74,6 @@
#include "scripting/lua_api.hpp" // for luaW_toboolean, etc
#include "scripting/lua_common.hpp"
#include "scripting/lua_cpp_function.hpp"
#include "scripting/lua_formula_bridge.hpp"
#include "scripting/lua_gui2.hpp" // for show_gamestate_inspector
#include "scripting/lua_pathfind_cost_calculator.hpp"
#include "scripting/lua_race.hpp"
@ -104,8 +103,6 @@
#include "units/ptr.hpp" // for unit_const_ptr, unit_ptr
#include "units/types.hpp" // for unit_type_data, unit_types, etc
#include "util.hpp" // for lexical_cast
#include "utils/markov_generator.hpp"
#include "utils/context_free_grammar_generator.hpp"
#include "variable.hpp" // for vconfig, etc
#include "variable_info.hpp"
#include "wml_exception.hpp"
@ -4454,69 +4451,6 @@ int game_lua_kernel::intf_toggle_fog(lua_State *L, const bool clear)
return 0;
}
static int intf_name_generator(lua_State *L)
{
std::string type = luaL_checkstring(L, 1);
name_generator* gen = nullptr;
if(type == "markov" || type == "markov_chain") {
std::vector<std::string> input;
if(lua_istable(L, 2)) {
input = lua_check<std::vector<std::string>>(L, 2);
} else {
input = utils::parenthetical_split(luaL_checkstring(L, 2));
}
int chain_sz = luaL_optinteger(L, 3, 2);
int max_len = luaL_optinteger(L, 4, 12);
gen = new(lua_newuserdata(L, sizeof(markov_generator)))
markov_generator(input, chain_sz, max_len);
// Ensure the pointer didn't change when cast
assert(static_cast<void*>(gen) == dynamic_cast<markov_generator*>(gen));
} else if(type == "context_free" || type == "cfg" || type == "CFG") {
void* buf = lua_newuserdata(L, sizeof(context_free_grammar_generator));
if(lua_istable(L, 2)) {
std::map<std::string, std::vector<std::string>> data;
for(lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) {
if(!lua_isstring(L, -2)) {
lua_pushstring(L, "CFG generator: invalid nonterminal name (must be a string)");
return lua_error(L);
}
if(lua_isstring(L, -1)) {
data[lua_tostring(L,-2)] = utils::split(lua_tostring(L,-1),'|');
} else if(lua_istable(L, -1)) {
data[lua_tostring(L,-2)] = lua_check<std::vector<std::string>>(L, -1);
} else {
lua_pushstring(L, "CFG generator: invalid noterminal value (must be a string or list of strings)");
return lua_error(L);
}
}
if(!data.empty()) {
gen = new(buf) context_free_grammar_generator(data);
}
} else {
gen = new(buf) context_free_grammar_generator(luaL_checkstring(L, 2));
}
if(gen) {
assert(static_cast<void*>(gen) == dynamic_cast<context_free_grammar_generator*>(gen));
}
} else {
return luaL_argerror(L, 1, "should be either 'markov_chain' or 'context_free'");
}
static const char*const generic_err = "error initializing name generator";
if(!gen) {
lua_pushstring(L, generic_err);
return lua_error(L);
}
// We set the metatable now, even if the generator is invalid, so that it
// will be properly collected if it was invalid.
luaL_getmetatable(L, "name generator");
lua_setmetatable(L, -2);
if(!gen->is_valid()) {
lua_pushstring(L, generic_err);
return lua_error(L);
}
return 1;
}
// END CALLBACK IMPLEMENTATION
game_board & game_lua_kernel::board() {
@ -4586,20 +4520,17 @@ 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 },
{ "debug_ai", &intf_debug_ai },
{ "eval_conditional", &intf_eval_conditional },
{ "eval_formula", &lua_formula_bridge::intf_eval_formula},
{ "get_era", &intf_get_era },
{ "get_image_size", &intf_get_image_size },
{ "get_time_stamp", &intf_get_time_stamp },
{ "get_traits", &intf_get_traits },
{ "get_viewing_side", &intf_get_viewing_side },
{ "modify_ai", &intf_modify_ai },
{ "name_generator", &intf_name_generator },
{ "set_music", &intf_set_music },
{ "transform_unit", &intf_transform_unit },
{ "unit_ability", &intf_unit_ability },
@ -4794,9 +4725,6 @@ 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);

View file

@ -292,5 +292,5 @@ std::string lua_formula_bridge::register_metatables(lua_State* L)
lua_setfield(L, -2, "__metatable");
lua_rawset(L, LUA_REGISTRYINDEX);
return "Adding formula metatable...";
return "Adding formula metatable...\n";
}

View file

@ -30,14 +30,19 @@
#include "scripting/lua_common.hpp"
#include "scripting/lua_cpp_function.hpp"
#include "scripting/lua_fileops.hpp"
#include "scripting/lua_formula_bridge.hpp"
#include "scripting/lua_gui2.hpp"
#include "scripting/lua_map_location_ops.hpp"
#include "scripting/lua_rng.hpp"
#include "scripting/lua_types.hpp"
#include "scripting/push_check.hpp"
#include "version.hpp" // for do_version_check, etc
#include "serialization/string_utils.hpp"
#include "utils/functional.hpp"
#include "utils/markov_generator.hpp"
#include "utils/context_free_grammar_generator.hpp"
#include <boost/scoped_ptr.hpp>
#include <cstring>
@ -57,6 +62,9 @@ static lg::log_domain log_scripting_lua("scripting/lua");
#define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
#define ERR_LUA LOG_STREAM(err, log_scripting_lua)
// Registry key for metatable
static const char * Gen = "name generator";
// Callback implementations
/**
@ -160,6 +168,82 @@ int lua_kernel_base::intf_show_lua_console(lua_State *L)
return lua_gui2::show_lua_console(L, *video_, this);
}
static int impl_name_generator_call(lua_State *L)
{
name_generator* gen = static_cast<name_generator*>(lua_touserdata(L, 1));
lua_pushstring(L, gen->generate().c_str());
return 1;
}
static int impl_name_generator_collect(lua_State *L)
{
name_generator* gen = static_cast<name_generator*>(lua_touserdata(L, 1));
gen->~name_generator();
return 0;
}
static int intf_name_generator(lua_State *L)
{
std::string type = luaL_checkstring(L, 1);
name_generator* gen = nullptr;
if(type == "markov" || type == "markov_chain") {
std::vector<std::string> input;
if(lua_istable(L, 2)) {
input = lua_check<std::vector<std::string>>(L, 2);
} else {
input = utils::parenthetical_split(luaL_checkstring(L, 2));
}
int chain_sz = luaL_optinteger(L, 3, 2);
int max_len = luaL_optinteger(L, 4, 12);
gen = new(lua_newuserdata(L, sizeof(markov_generator))) markov_generator(input, chain_sz, max_len);
// Ensure the pointer didn't change when cast
assert(static_cast<void*>(gen) == dynamic_cast<markov_generator*>(gen));
} else if(type == "context_free" || type == "cfg" || type == "CFG") {
void* buf = lua_newuserdata(L, sizeof(context_free_grammar_generator));
if(lua_istable(L, 2)) {
std::map<std::string, std::vector<std::string>> data;
for(lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) {
if(!lua_isstring(L, -2)) {
lua_pushstring(L, "CFG generator: invalid nonterminal name (must be a string)");
return lua_error(L);
}
if(lua_isstring(L, -1)) {
data[lua_tostring(L,-2)] = utils::split(lua_tostring(L,-1),'|');
} else if(lua_istable(L, -1)) {
data[lua_tostring(L,-2)] = lua_check<std::vector<std::string>>(L, -1);
} else {
lua_pushstring(L, "CFG generator: invalid noterminal value (must be a string or list of strings)");
return lua_error(L);
}
}
if(!data.empty()) {
gen = new(buf) context_free_grammar_generator(data);
}
} else {
gen = new(buf) context_free_grammar_generator(luaL_checkstring(L, 2));
}
if(gen) {
assert(static_cast<void*>(gen) == dynamic_cast<context_free_grammar_generator*>(gen));
}
} else {
return luaL_argerror(L, 1, "should be either 'markov_chain' or 'context_free'");
}
static const char*const generic_err = "error initializing name generator";
if(!gen) {
lua_pushstring(L, generic_err);
return lua_error(L);
}
// We set the metatable now, even if the generator is invalid, so that it
// will be properly collected if it was invalid.
luaL_getmetatable(L, Gen);
lua_setmetatable(L, -2);
if(!gen->is_valid()) {
lua_pushstring(L, generic_err);
return lua_error(L);
}
return 1;
}
// End Callback implementations
// Template which allows to push member functions to the lua kernel base into lua as C functions, using a shim
@ -283,6 +367,9 @@ lua_kernel_base::lua_kernel_base(CVideo * video)
{ "show_message_dialog", &dispatch<&lua_kernel_base::intf_show_message_dialog> },
{ "show_popup_dialog", &dispatch<&lua_kernel_base::intf_show_popup_dialog> },
{ "show_lua_console", &dispatch<&lua_kernel_base::intf_show_lua_console> },
{ "compile_formula", &lua_formula_bridge::intf_compile_formula},
{ "eval_formula", &lua_formula_bridge::intf_eval_formula},
{ "name_generator", &intf_name_generator },
{ nullptr, nullptr }
};
@ -349,9 +436,22 @@ lua_kernel_base::lua_kernel_base(CVideo * video)
cmd_log_ << "Adding rng tables...\n";
lua_rng::load_tables(L);
cmd_log_ << "Adding name generator metatable...\n";
luaL_newmetatable(L, Gen);
static luaL_Reg const generator[] = {
{ "__call", &impl_name_generator_call},
{ "__gc", &impl_name_generator_collect},
{ nullptr, nullptr}
};
luaL_setfuncs(L, generator, 0);
// Create formula bridge metatables
cmd_log_ << lua_formula_bridge::register_metatables(L);
// Loading ilua:
cmd_log_ << "Loading ilua...\n";
lua_settop(L, 0);
lua_pushstring(L, "lua/ilua.lua");
int result = intf_require(L);
if (result == 1) {

View file

@ -17,7 +17,6 @@
#include "units/race.hpp"
#include "scripting/lua_common.hpp"
#include "units/types.hpp"
#include "utils/name_generator.hpp"
#include <string>
#include <string.h>
@ -92,20 +91,6 @@ static int impl_race_get(lua_State* L)
return 0;
}
static int impl_name_generator_call(lua_State *L)
{
name_generator* gen = static_cast<name_generator*>(lua_touserdata(L, 1));
lua_pushstring(L, gen->generate().c_str());
return 1;
}
static int impl_name_generator_collect(lua_State *L)
{
name_generator* gen = static_cast<name_generator*>(lua_touserdata(L, 1));
gen->~name_generator();
return 0;
}
namespace lua_race {
std::string register_metatable(lua_State * L)
@ -120,14 +105,6 @@ namespace lua_race {
lua_pushstring(L, "race");
lua_setfield(L, -2, "__metatable");
luaL_newmetatable(L, Gen);
static luaL_Reg const generator[] = {
{ "__call", &impl_name_generator_call},
{ "__gc", &impl_name_generator_collect},
{ nullptr, nullptr}
};
luaL_setfuncs(L, generator, 0);
return "Adding getrace metatable...\n";
}