Skip to content

Commit

Permalink
Implement WFL function symbol table inheritance
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
CelticMinstrel committed Apr 3, 2017
1 parent 06de10f commit 9ec2403
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 78 deletions.
31 changes: 1 addition & 30 deletions src/ai/formula/function_table.cpp
Expand Up @@ -1133,18 +1133,6 @@ class move_partial_function : public function_expression {
};


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)
Expand Down Expand Up @@ -1191,21 +1179,6 @@ class attack_function : public function_expression {
}
};


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)
Expand Down Expand Up @@ -1623,7 +1596,7 @@ class ai_formula_function : public formula_function {
#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);
Expand All @@ -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);
Expand Down
15 changes: 9 additions & 6 deletions src/formula/formula.cpp
Expand Up @@ -86,11 +86,8 @@ class function_list_expression : public formula_expression {
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);
}
Expand Down Expand Up @@ -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 &&
Expand Down Expand Up @@ -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);
Expand Down
95 changes: 59 additions & 36 deletions src/formula/function.cpp
Expand Up @@ -56,7 +56,7 @@ std::string function_expression::str() const
return s.str();
}

namespace {
namespace builtins {

class debug_function : public function_expression {
public:
Expand Down Expand Up @@ -1456,7 +1456,34 @@ class type_function : public function_expression {
}
};

}
} // 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
{
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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;
return &functions_table;
}

std::vector<std::string> builtin_function_names()
{
return get_functions_map().get_function_names();
action_function_symbol_table::action_function_symbol_table() {
using namespace actions;
function_symbol_table& functions_table = *this;
FUNCTION(safe_call);
FUNCTION(set_var);
}

}
17 changes: 11 additions & 6 deletions src/formula/function.hpp
Expand Up @@ -19,6 +19,8 @@
#include "formula/formula.hpp"
#include "formula/callable.hpp"

#include <set>

namespace game_logic {

class formula_expression {
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 9ec2403

Please sign in to comment.