Add builtin functions for calc
This commit is contained in:
parent
b3cbd2d499
commit
0ebb56eb7c
|
@ -1,9 +1,43 @@
|
|||
#include "AST.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace calc {
|
||||
|
||||
namespace {
|
||||
using d2dfn = double(*)(double);
|
||||
std::function<double(const Variables&, const Functions&, FunctionArguments&)> wrap(std::function<double(double)> fn) {
|
||||
return [fn](const Variables& vars, const Functions& funs, FunctionArguments& args) -> double{
|
||||
if (args.size() != 1)
|
||||
return 0;
|
||||
return fn(args[0]->eval(vars, funs));
|
||||
};
|
||||
}
|
||||
|
||||
std::map<std::string, std::function<double(const Variables&, const Functions&, FunctionArguments&)>> builtins =
|
||||
{
|
||||
{"if", [](const Variables& vars, const Functions& funs, FunctionArguments& args) -> double {
|
||||
if (args.size() != 3)
|
||||
return 0;
|
||||
double test = args[0]->eval(vars, funs);
|
||||
if (std::fabs(test) < 1e-8)
|
||||
return args[2]->eval(vars, funs);
|
||||
else
|
||||
return args[1]->eval(vars, funs);
|
||||
}},
|
||||
{"sin", wrap((d2dfn)(std::sin))},
|
||||
{"cos", wrap((d2dfn)(std::cos))},
|
||||
{"tan", wrap((d2dfn)(std::tan))},
|
||||
{"asin", wrap((d2dfn)(std::asin))},
|
||||
{"acos", wrap((d2dfn)(std::acos))},
|
||||
{"atan", wrap((d2dfn)(std::atan))},
|
||||
{"abs", wrap((d2dfn)(std::fabs))}
|
||||
};
|
||||
}
|
||||
|
||||
Number::Number(double d) : m_val(d) {}
|
||||
double Number::eval(const Variables&, const Functions&) const {
|
||||
return m_val;
|
||||
|
@ -74,8 +108,13 @@ std::size_t FunctionArguments::size() const {
|
|||
FunctionCall::FunctionCall(std::string name, std::unique_ptr<FunctionArguments>&& arguments) : m_name(name), m_arguments(std::move(arguments)) {}
|
||||
double FunctionCall::eval(const Variables& vars, const Functions& funs) const {
|
||||
auto fp = funs.find(m_name);
|
||||
if (fp == funs.end())
|
||||
return 0;
|
||||
if (fp == funs.end()) {
|
||||
if (builtins.count(m_name)) {
|
||||
return builtins[m_name](vars, funs, *m_arguments);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Function& fun = *dynamic_cast<Function*>((fp->second.get()));
|
||||
|
||||
if (m_arguments->size() != fun.getParams().size()) return 0;
|
||||
|
|
Loading…
Reference in New Issue