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:
Charles Dang 2017-11-14 16:29:41 +11:00
parent 6713070cc5
commit e50a63927b
2 changed files with 1267 additions and 1395 deletions

File diff suppressed because it is too large Load diff

View file

@ -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