WFL/Formula: cleaned up formatting and greatly reduced code duplication
I added a helper macro to define the various function classes.
This commit is contained in:
parent
6713070cc5
commit
e50a63927b
2 changed files with 1267 additions and 1395 deletions
File diff suppressed because it is too large
Load diff
|
@ -15,51 +15,93 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "formula/formula.hpp"
|
||||
#include "formula/callable.hpp"
|
||||
#include "formula/formula.hpp"
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace wfl {
|
||||
namespace wfl
|
||||
{
|
||||
/** Helper macro to declare an associated class for a WFL function. */
|
||||
#define DEFINE_WFL_FUNCTION(name, min_args, max_args) \
|
||||
class name##_function : public function_expression \
|
||||
{ \
|
||||
public: \
|
||||
explicit name##_function(const args_list& args) \
|
||||
: function_expression(#name, args, ##min_args, ##max_args) \
|
||||
{ \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
variant execute(const formula_callable& variables, formula_debugger* fdb) const; \
|
||||
}; \
|
||||
\
|
||||
variant name##_function::execute(const formula_callable& variables, formula_debugger* fdb) const
|
||||
|
||||
struct call_stack_manager {
|
||||
|
||||
/**
|
||||
* Declares a function `name` in the local function table `functions_table`.
|
||||
* The function must be defined by a `name_function` class which is accessible in the current scope.
|
||||
*/
|
||||
#define DECLARE_WFL_FUNCTION(name) \
|
||||
functions_table.add_function(#name, formula_function_ptr(new builtin_formula_function<name##_function>(#name)))
|
||||
|
||||
struct call_stack_manager
|
||||
{
|
||||
explicit call_stack_manager(const std::string& str);
|
||||
~call_stack_manager();
|
||||
|
||||
static std::string get();
|
||||
};
|
||||
|
||||
class formula_expression {
|
||||
class formula_expression
|
||||
{
|
||||
public:
|
||||
explicit formula_expression(const std::string& name = "") : name_(name) {}
|
||||
virtual ~formula_expression() {}
|
||||
variant evaluate(const formula_callable& variables, formula_debugger *fdb = nullptr) const {
|
||||
explicit formula_expression(const std::string& name = "")
|
||||
: name_(name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~formula_expression()
|
||||
{
|
||||
}
|
||||
|
||||
variant evaluate(const formula_callable& variables, formula_debugger* fdb = nullptr) const
|
||||
{
|
||||
call_stack_manager manager(name_);
|
||||
if (fdb!=nullptr) {
|
||||
return evaluate_arg_callback(*fdb,*this,variables);
|
||||
|
||||
if(fdb != nullptr) {
|
||||
return evaluate_arg_callback(*fdb, *this, variables);
|
||||
} else {
|
||||
return execute(variables,fdb);
|
||||
return execute(variables, fdb);
|
||||
}
|
||||
}
|
||||
|
||||
std::string get_name() const { return name_; }
|
||||
std::string get_name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
virtual std::string str() const = 0;
|
||||
|
||||
private:
|
||||
virtual variant execute(const formula_callable& variables, formula_debugger *fdb = nullptr) const = 0;
|
||||
virtual variant execute(const formula_callable& variables, formula_debugger* fdb = nullptr) const = 0;
|
||||
|
||||
const std::string name_;
|
||||
friend class formula_debugger;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<formula_expression> expression_ptr;
|
||||
|
||||
class function_expression : public formula_expression {
|
||||
class function_expression : public formula_expression
|
||||
{
|
||||
public:
|
||||
typedef std::vector<expression_ptr> args_list;
|
||||
explicit function_expression(
|
||||
const std::string& name,
|
||||
const args_list& args,
|
||||
int min_args=-1, int max_args=-1)
|
||||
: formula_expression(name), args_(args)
|
||||
|
||||
explicit function_expression(const std::string& name, const args_list& args, int min_args = -1, int max_args = -1)
|
||||
: formula_expression(name)
|
||||
, args_(args)
|
||||
{
|
||||
if(min_args >= 0 && args_.size() < static_cast<size_t>(min_args)) {
|
||||
throw formula_error("Too few arguments", "", "", 0);
|
||||
|
@ -69,68 +111,112 @@ public:
|
|||
throw formula_error("Too many arguments", "", "", 0);
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::string str() const;
|
||||
|
||||
protected:
|
||||
const args_list& args() const { return args_; }
|
||||
const args_list& args() const
|
||||
{
|
||||
return args_;
|
||||
}
|
||||
|
||||
private:
|
||||
args_list args_;
|
||||
};
|
||||
|
||||
class key_value_pair : public formula_callable {
|
||||
class key_value_pair : public formula_callable
|
||||
{
|
||||
public:
|
||||
explicit key_value_pair(const variant& key, const variant& value)
|
||||
: key_(key)
|
||||
, value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
void serialize_to_string(std::string& str) const override;
|
||||
|
||||
private:
|
||||
variant key_;
|
||||
variant value_;
|
||||
|
||||
variant get_value(const std::string& key) const override;
|
||||
|
||||
void get_inputs(formula_input_vector& inputs) const override;
|
||||
public:
|
||||
explicit key_value_pair(const variant& key, const variant& value) : key_(key), value_(value) {}
|
||||
|
||||
void serialize_to_string(std::string& str) const override;
|
||||
};
|
||||
|
||||
class formula_function_expression : public function_expression {
|
||||
class formula_function_expression : public function_expression
|
||||
{
|
||||
public:
|
||||
explicit formula_function_expression(const std::string& name, const args_list& args, const_formula_ptr formula, const_formula_ptr precondition, const std::vector<std::string>& arg_names);
|
||||
explicit formula_function_expression(const std::string& name,
|
||||
const args_list& args,
|
||||
const_formula_ptr formula,
|
||||
const_formula_ptr precondition,
|
||||
const std::vector<std::string>& arg_names);
|
||||
|
||||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger *fdb) const;
|
||||
variant execute(const formula_callable& variables, formula_debugger* fdb) const;
|
||||
|
||||
const_formula_ptr formula_;
|
||||
const_formula_ptr precondition_;
|
||||
|
||||
std::vector<std::string> arg_names_;
|
||||
|
||||
int star_arg_;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<function_expression> function_expression_ptr;
|
||||
|
||||
class formula_function {
|
||||
class formula_function
|
||||
{
|
||||
public:
|
||||
formula_function(const std::string name)
|
||||
: name_(name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual function_expression_ptr generate_function_expression(const std::vector<expression_ptr>& args) const = 0;
|
||||
|
||||
virtual ~formula_function()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string name_;
|
||||
public:
|
||||
formula_function(const std::string name) : name_(name) {}
|
||||
virtual function_expression_ptr generate_function_expression(const std::vector<expression_ptr>& args) const = 0;
|
||||
virtual ~formula_function() {}
|
||||
};
|
||||
|
||||
class user_formula_function : public formula_function {
|
||||
const_formula_ptr formula_;
|
||||
const_formula_ptr precondition_;
|
||||
std::vector<std::string> args_;
|
||||
class user_formula_function : public formula_function
|
||||
{
|
||||
public:
|
||||
user_formula_function(const std::string& name, const_formula_ptr formula, const_formula_ptr precondition, const std::vector<std::string>& args)
|
||||
user_formula_function(const std::string& name,
|
||||
const_formula_ptr formula,
|
||||
const_formula_ptr precondition,
|
||||
const std::vector<std::string>& args)
|
||||
: formula_function(name)
|
||||
, formula_(formula)
|
||||
, precondition_(precondition)
|
||||
, args_(args)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
function_expression_ptr generate_function_expression(const std::vector<expression_ptr>& args) const;
|
||||
|
||||
private:
|
||||
const_formula_ptr formula_;
|
||||
const_formula_ptr precondition_;
|
||||
std::vector<std::string> args_;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class builtin_formula_function : public formula_function {
|
||||
class builtin_formula_function : public formula_function
|
||||
{
|
||||
public:
|
||||
builtin_formula_function(const std::string& name) : formula_function(name) {}
|
||||
function_expression_ptr generate_function_expression(const std::vector<expression_ptr>& args) const {
|
||||
builtin_formula_function(const std::string& name)
|
||||
: formula_function(name)
|
||||
{
|
||||
}
|
||||
|
||||
function_expression_ptr generate_function_expression(const std::vector<expression_ptr>& args) const
|
||||
{
|
||||
return function_expression_ptr(new T(args));
|
||||
}
|
||||
};
|
||||
|
@ -138,31 +224,42 @@ public:
|
|||
typedef std::shared_ptr<formula_function> formula_function_ptr;
|
||||
typedef std::map<std::string, formula_function_ptr> functions_map;
|
||||
|
||||
class function_symbol_table {
|
||||
std::shared_ptr<function_symbol_table> parent;
|
||||
functions_map custom_formulas_;
|
||||
enum builtins_tag_t {builtins_tag};
|
||||
function_symbol_table(builtins_tag_t) {}
|
||||
class function_symbol_table
|
||||
{
|
||||
public:
|
||||
explicit function_symbol_table(std::shared_ptr<function_symbol_table> parent = nullptr);
|
||||
|
||||
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::set<std::string> get_function_names() const;
|
||||
bool empty() {return custom_formulas_.empty() && (parent == nullptr || parent->empty());}
|
||||
|
||||
bool empty()
|
||||
{
|
||||
return custom_formulas_.empty() && (parent == nullptr || parent->empty());
|
||||
}
|
||||
|
||||
static std::shared_ptr<function_symbol_table> get_builtins();
|
||||
|
||||
private:
|
||||
std::shared_ptr<function_symbol_table> parent;
|
||||
functions_map custom_formulas_;
|
||||
|
||||
enum builtins_tag_t { builtins_tag };
|
||||
function_symbol_table(builtins_tag_t)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class action_function_symbol_table : public function_symbol_table {
|
||||
class action_function_symbol_table : public function_symbol_table
|
||||
{
|
||||
public:
|
||||
action_function_symbol_table(std::shared_ptr<function_symbol_table> parent = nullptr);
|
||||
};
|
||||
|
||||
/// Declares a function `name` in the local function table `functions_table`.
|
||||
/// The function must be defined by a `name_function` class which is accessible in the current scope.
|
||||
#define DECLARE_WFL_FUNCTION(name) functions_table.add_function(#name, \
|
||||
formula_function_ptr(new builtin_formula_function<name##_function>(#name)))
|
||||
|
||||
class wrapper_formula : public formula_expression {
|
||||
class wrapper_formula : public formula_expression
|
||||
{
|
||||
public:
|
||||
wrapper_formula()
|
||||
: arg_()
|
||||
|
@ -170,7 +267,8 @@ public:
|
|||
}
|
||||
|
||||
wrapper_formula(expression_ptr arg)
|
||||
: formula_expression(arg ? arg->get_name() : ""), arg_(arg)
|
||||
: formula_expression(arg ? arg->get_name() : "")
|
||||
, arg_(arg)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -180,22 +278,23 @@ public:
|
|||
|
||||
virtual std::string str() const
|
||||
{
|
||||
if (arg_) {
|
||||
if(arg_) {
|
||||
return arg_->str();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
virtual variant execute(const formula_callable& variables, formula_debugger *fdb = nullptr) const
|
||||
virtual variant execute(const formula_callable& variables, formula_debugger* fdb = nullptr) const
|
||||
{
|
||||
if (arg_) {
|
||||
return arg_->evaluate(variables,fdb);
|
||||
if(arg_) {
|
||||
return arg_->evaluate(variables, fdb);
|
||||
} else {
|
||||
return variant();
|
||||
}
|
||||
}
|
||||
|
||||
expression_ptr arg_;
|
||||
};
|
||||
|
||||
}
|
||||
} // end namespace wfl
|
||||
|
|
Loading…
Add table
Reference in a new issue