-
-
Notifications
You must be signed in to change notification settings - Fork 988
/
function.hpp
189 lines (158 loc) · 5.34 KB
/
function.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/*
Copyright (C) 2008 - 2016 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#ifndef FORMULA_FUNCTION_HPP_INCLUDED
#define FORMULA_FUNCTION_HPP_INCLUDED
#include "formula/formula.hpp"
#include "formula/callable.hpp"
namespace game_logic {
class formula_expression {
public:
formula_expression() : 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);
} else {
return execute(variables,fdb);
}
}
void set_name(const char* name) { name_ = name; }
const char* 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;
const char* name_;
friend class formula_debugger;
};
typedef boost::shared_ptr<formula_expression> expression_ptr;
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)
: name_(name), args_(args)
{
set_name(name.c_str());
if(min_args >= 0 && args_.size() < static_cast<size_t>(min_args)) {
throw formula_error("Too few arguments", "", "", 0);
}
if(max_args >= 0 && args_.size() > static_cast<size_t>(max_args)) {
throw formula_error("Too many arguments", "", "", 0);
}
}
virtual std::string str() const;
protected:
const args_list& args() const { return args_; }
private:
std::string name_;
args_list args_;
};
class key_value_pair : public formula_callable {
variant key_;
variant value_;
variant get_value(const std::string& key) const;
void get_inputs(std::vector<game_logic::formula_input>* inputs) const;
public:
explicit key_value_pair(const variant& key, const variant& value) : key_(key), value_(value) {}
void serialize_to_string(std::string& str) const;
};
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);
private:
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 boost::shared_ptr<function_expression> function_expression_ptr;
class 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_;
public:
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;
};
template<typename T>
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 {
return function_expression_ptr(new T(args));
}
};
typedef boost::shared_ptr<formula_function> formula_function_ptr;
typedef std::map<std::string, formula_function_ptr> functions_map;
class function_symbol_table {
functions_map custom_formulas_;
public:
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;
bool empty() {return custom_formulas_.empty();}
};
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 wrapper_formula : public formula_expression {
public:
wrapper_formula()
: arg_()
{
}
wrapper_formula(expression_ptr arg)
: arg_(arg)
{
}
virtual ~wrapper_formula()
{
}
virtual std::string str() const
{
if (arg_) {
return arg_->str();
} else {
return "";
}
}
private:
virtual variant execute(const formula_callable& variables, formula_debugger *fdb = nullptr) const
{
if (arg_) {
return arg_->evaluate(variables,fdb);
} else {
return variant();
}
}
expression_ptr arg_;
};
}
#endif