mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-06 02:23:16 +00:00
Implement WFL function symbol table inheritance
This also adds a new intermediary "action" function table between the FormulaAI function table and the builtins function table. This "actions" function table could be used in other areas of the code where action objects are desired, for example in scenario events or in the GUI2 Canvas.
This commit is contained in:
parent
c2ba1c5c6f
commit
aedf953d28
@ -1133,18 +1133,6 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class set_var_function : public function_expression {
|
||||
public:
|
||||
explicit set_var_function(const args_list& args)
|
||||
: function_expression("set_var", args, 2, 2)
|
||||
{}
|
||||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
|
||||
return variant(new set_var_callable(args()[0]->evaluate(variables,add_debug_info(fdb,0,"set_var:key")).as_string(), args()[1]->evaluate(variables,add_debug_info(fdb,1,"set_var:value"))));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class set_unit_var_function : public function_expression {
|
||||
public:
|
||||
explicit set_unit_var_function(const args_list& args)
|
||||
@ -1191,21 +1179,6 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class safe_call_function : public function_expression {
|
||||
public:
|
||||
explicit safe_call_function(const args_list& args)
|
||||
: function_expression("safe_call", args, 2, 2)
|
||||
{}
|
||||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
|
||||
const variant main = args()[0]->evaluate(variables,fdb);
|
||||
const expression_ptr backup_formula = args()[1];
|
||||
|
||||
return variant(new safe_call_callable(main, backup_formula));
|
||||
}
|
||||
};
|
||||
|
||||
class debug_label_function : public function_expression {
|
||||
public:
|
||||
explicit debug_label_function(const args_list& args, const formula_ai& ai)
|
||||
@ -1623,7 +1596,7 @@ public:
|
||||
#define FUNCTION(name) add_function(#name, formula_function_ptr( \
|
||||
new builtin_formula_function<name##_function>(#name)))
|
||||
|
||||
ai_function_symbol_table::ai_function_symbol_table(ai::formula_ai& ai) {
|
||||
ai_function_symbol_table::ai_function_symbol_table(ai::formula_ai& ai) : function_symbol_table(new action_function_symbol_table) {
|
||||
FUNCTION(outcomes);
|
||||
//AI_FUNCTION(evaluate_for_position);
|
||||
FUNCTION(move);
|
||||
@ -1632,14 +1605,12 @@ ai_function_symbol_table::ai_function_symbol_table(ai::formula_ai& ai) {
|
||||
AI_FUNCTION(rate_action);
|
||||
FUNCTION(recall);
|
||||
FUNCTION(recruit);
|
||||
FUNCTION(safe_call);
|
||||
FUNCTION(get_unit_type);
|
||||
AI_FUNCTION(is_avoided_location);
|
||||
FUNCTION(is_village);
|
||||
AI_FUNCTION(is_unowned_village);
|
||||
FUNCTION(unit_at);
|
||||
AI_FUNCTION(unit_moves);
|
||||
FUNCTION(set_var);
|
||||
FUNCTION(set_unit_var);
|
||||
FUNCTION(fallback);
|
||||
FUNCTION(units_can_reach);
|
||||
|
@ -86,11 +86,8 @@ public:
|
||||
private:
|
||||
variant execute(const formula_callable& /*variables*/, formula_debugger * /*fdb*/) const {
|
||||
std::vector<variant> res;
|
||||
std::vector<std::string> function_names = builtin_function_names();
|
||||
std::vector<std::string> more_function_names = symbols_->get_function_names();
|
||||
function_names.insert(function_names.end(), more_function_names.begin(), more_function_names.end());
|
||||
for(size_t i = 0; i < function_names.size(); i++) {
|
||||
res.emplace_back(function_names[i]);
|
||||
for(const std::string& fcn_name : symbols_->get_function_names()) {
|
||||
res.emplace_back(fcn_name);
|
||||
}
|
||||
return variant(res);
|
||||
}
|
||||
@ -1001,6 +998,12 @@ expression_ptr parse_expression(const token* i1, const token* i2, function_symbo
|
||||
throw formula_error("Empty expression", "", *i1->filename, i1->line_number);
|
||||
}
|
||||
|
||||
std::unique_ptr<function_symbol_table> temp_functions;
|
||||
if(!symbols) {
|
||||
temp_functions.reset(new function_symbol_table(function_symbol_table::get_builtins()));
|
||||
symbols = temp_functions.get();
|
||||
}
|
||||
|
||||
const token* begin = i1, *end = i2; //these are used for error reporting
|
||||
|
||||
if(i1->type == TOKEN_KEYWORD &&
|
||||
@ -1153,7 +1156,7 @@ expression_ptr parse_expression(const token* i1, const token* i2, function_symbo
|
||||
std::vector<expression_ptr> args;
|
||||
parse_args(i1+2,i2-1,&args,symbols);
|
||||
try{
|
||||
return create_function(std::string(i1->begin,i1->end),args,symbols);
|
||||
return symbols->create_function(std::string(i1->begin,i1->end),args);
|
||||
}
|
||||
catch(formula_error& e) {
|
||||
throw formula_error(e.type, tokens_to_string(function_call_begin, function_call_end), *i1->filename, i1->line_number);
|
||||
|
@ -56,7 +56,7 @@ std::string function_expression::str() const
|
||||
return s.str();
|
||||
}
|
||||
|
||||
namespace {
|
||||
namespace builtins {
|
||||
|
||||
class debug_function : public function_expression {
|
||||
public:
|
||||
@ -1456,7 +1456,34 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace builtins
|
||||
|
||||
namespace actions {
|
||||
|
||||
class safe_call_function : public function_expression {
|
||||
public:
|
||||
explicit safe_call_function(const args_list& args)
|
||||
: function_expression("safe_call", args, 2, 2) {}
|
||||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
|
||||
const variant main = args()[0]->evaluate(variables, fdb);
|
||||
const expression_ptr backup_formula = args()[1];
|
||||
|
||||
return variant(new safe_call_callable(main, backup_formula));
|
||||
}
|
||||
};
|
||||
|
||||
class set_var_function : public function_expression {
|
||||
public:
|
||||
explicit set_var_function(const args_list& args)
|
||||
: function_expression("set_var", args, 2, 2) {}
|
||||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
|
||||
return variant(new set_var_callable(args()[0]->evaluate(variables, add_debug_info(fdb, 0, "set_var:key")).as_string(), args()[1]->evaluate(variables, add_debug_info(fdb, 1, "set_var:value"))));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace actions
|
||||
|
||||
variant key_value_pair::get_value(const std::string& key) const
|
||||
{
|
||||
@ -1535,6 +1562,12 @@ function_expression_ptr user_formula_function::generate_function_expression(cons
|
||||
return function_expression_ptr(new formula_function_expression(name_, args, formula_, precondition_, args_));
|
||||
}
|
||||
|
||||
function_symbol_table::function_symbol_table(function_symbol_table* parent) : parent(parent) {}
|
||||
|
||||
function_symbol_table::~function_symbol_table() {
|
||||
if(parent) delete parent;
|
||||
}
|
||||
|
||||
void function_symbol_table::add_function(const std::string& name, formula_function_ptr fcn)
|
||||
{
|
||||
custom_formulas_[name] = fcn;
|
||||
@ -1547,26 +1580,36 @@ expression_ptr function_symbol_table::create_function(const std::string& fn, con
|
||||
return i->second->generate_function_expression(args);
|
||||
}
|
||||
|
||||
return expression_ptr();
|
||||
expression_ptr res((parent ? parent : get_builtins())->create_function(fn, args));
|
||||
if(res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
throw formula_error("Unknown function: " + fn, "", "", 0);
|
||||
}
|
||||
|
||||
std::vector<std::string> function_symbol_table::get_function_names() const
|
||||
std::set<std::string> function_symbol_table::get_function_names() const
|
||||
{
|
||||
std::vector<std::string> res;
|
||||
std::set<std::string> res;
|
||||
if(parent) {
|
||||
res = parent->get_function_names();
|
||||
} else if(this != get_builtins()) {
|
||||
res = get_builtins()->get_function_names();
|
||||
}
|
||||
for(functions_map::const_iterator iter = custom_formulas_.begin(); iter != custom_formulas_.end(); ++iter ) {
|
||||
res.push_back((*iter).first);
|
||||
res.insert((*iter).first);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
namespace {
|
||||
#define FUNCTION(name) functions_table.add_function(#name, \
|
||||
formula_function_ptr(new builtin_formula_function<name##_function>(#name)))
|
||||
|
||||
function_symbol_table& get_functions_map() {
|
||||
function_symbol_table* function_symbol_table::get_builtins() {
|
||||
static function_symbol_table functions_table;
|
||||
|
||||
if(functions_table.empty()) {
|
||||
#define FUNCTION(name) functions_table.add_function(#name, \
|
||||
formula_function_ptr(new builtin_formula_function<name##_function>(#name)))
|
||||
using namespace builtins;
|
||||
FUNCTION(debug);
|
||||
FUNCTION(dir);
|
||||
FUNCTION(if);
|
||||
@ -1627,36 +1670,16 @@ function_symbol_table& get_functions_map() {
|
||||
FUNCTION(pi);
|
||||
FUNCTION(hypot);
|
||||
FUNCTION(type);
|
||||
#undef FUNCTION
|
||||
}
|
||||
|
||||
return functions_table;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
expression_ptr create_function(const std::string& fn,
|
||||
const std::vector<expression_ptr>& args,
|
||||
const function_symbol_table* symbols)
|
||||
{
|
||||
if(symbols) {
|
||||
expression_ptr res(symbols->create_function(fn, args));
|
||||
if(res) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
expression_ptr res(get_functions_map().create_function(fn, args));
|
||||
if(!res) {
|
||||
throw formula_error("Unknown function: " + fn, "", "", 0);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<std::string> builtin_function_names()
|
||||
{
|
||||
return get_functions_map().get_function_names();
|
||||
return &functions_table;
|
||||
}
|
||||
|
||||
action_function_symbol_table::action_function_symbol_table() {
|
||||
using namespace actions;
|
||||
function_symbol_table& functions_table = *this;
|
||||
FUNCTION(safe_call);
|
||||
FUNCTION(set_var);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include "formula/formula.hpp"
|
||||
#include "formula/callable.hpp"
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace game_logic {
|
||||
|
||||
class formula_expression {
|
||||
@ -134,19 +136,22 @@ typedef std::shared_ptr<formula_function> formula_function_ptr;
|
||||
typedef std::map<std::string, formula_function_ptr> functions_map;
|
||||
|
||||
class function_symbol_table {
|
||||
function_symbol_table* parent = nullptr;
|
||||
functions_map custom_formulas_;
|
||||
public:
|
||||
explicit function_symbol_table(function_symbol_table* parent = nullptr);
|
||||
~function_symbol_table();
|
||||
void add_function(const std::string& name, formula_function_ptr fcn);
|
||||
expression_ptr create_function(const std::string& fn, const std::vector<expression_ptr>& args) const;
|
||||
std::vector<std::string> get_function_names() const;
|
||||
std::set<std::string> get_function_names() const;
|
||||
bool empty() {return custom_formulas_.empty();}
|
||||
static function_symbol_table* get_builtins();
|
||||
};
|
||||
|
||||
expression_ptr create_function(const std::string& fn,
|
||||
const std::vector<expression_ptr>& args,
|
||||
const function_symbol_table* symbols);
|
||||
std::vector<std::string> builtin_function_names();
|
||||
|
||||
class action_function_symbol_table : public function_symbol_table {
|
||||
public:
|
||||
action_function_symbol_table();
|
||||
};
|
||||
|
||||
class wrapper_formula : public formula_expression {
|
||||
public:
|
||||
|
Loading…
x
Reference in New Issue
Block a user