mirror of
https://github.com/aportelli/LatAnalyze.git
synced 2025-04-10 19:20:44 +01:00
significant optimisation of the math interpreter using integer address tables for variables and functions
This commit is contained in:
parent
b0f6c30445
commit
47e159e041
@ -21,7 +21,7 @@ int main(int argc, char* argv[])
|
|||||||
RunContext context;
|
RunContext context;
|
||||||
|
|
||||||
cout << "-- Source code:" << endl << source << endl << endl;
|
cout << "-- Source code:" << endl << source << endl << endl;
|
||||||
interpreter.compile();
|
interpreter.compile(context);
|
||||||
cout << "-- Abstract Syntax Tree:" << endl;
|
cout << "-- Abstract Syntax Tree:" << endl;
|
||||||
if (interpreter.getAST())
|
if (interpreter.getAST())
|
||||||
{
|
{
|
||||||
@ -32,7 +32,18 @@ int main(int argc, char* argv[])
|
|||||||
cout << "<null>" << endl << endl;
|
cout << "<null>" << endl << endl;
|
||||||
}
|
}
|
||||||
cout << "-- Program:" << endl << interpreter << endl;
|
cout << "-- Program:" << endl << interpreter << endl;
|
||||||
StdMath::addStdMathFunc(context.fTable);
|
cout << "-- Variable table:" << endl;
|
||||||
|
for (auto &v: context.vTable)
|
||||||
|
{
|
||||||
|
cout << "'" << v.first << "': " << v.second << endl;
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
cout << "-- Function table:" << endl;
|
||||||
|
for (auto &f: context.fTable)
|
||||||
|
{
|
||||||
|
cout << "'" << f.first << "': " << f.second << endl;
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
interpreter(context);
|
interpreter(context);
|
||||||
if (!context.dStack.empty())
|
if (!context.dStack.empty())
|
||||||
{
|
{
|
||||||
|
@ -44,7 +44,23 @@ void CompiledDoubleFunction::setCode(const string &code)
|
|||||||
{
|
{
|
||||||
interpreter_.reset(new MathInterpreter(code));
|
interpreter_.reset(new MathInterpreter(code));
|
||||||
context_.reset(new RunContext);
|
context_.reset(new RunContext);
|
||||||
StdMath::addStdMathFunc(context_->fTable);
|
varAddress_.reset(new std::vector<unsigned int>);
|
||||||
|
isCompiled_.reset(new bool(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
// compile /////////////////////////////////////////////////////////////////////
|
||||||
|
void CompiledDoubleFunction::compile(void) const
|
||||||
|
{
|
||||||
|
if (!*isCompiled_)
|
||||||
|
{
|
||||||
|
interpreter_->compile(*(context_));
|
||||||
|
varAddress_->clear();
|
||||||
|
for (Index i = 0; i < getNArg(); ++i)
|
||||||
|
{
|
||||||
|
varAddress_->push_back(context_->vTable.at("x_" + strFrom(i)));
|
||||||
|
}
|
||||||
|
*isCompiled_ = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// function call ///////////////////////////////////////////////////////////////
|
// function call ///////////////////////////////////////////////////////////////
|
||||||
@ -52,9 +68,10 @@ double CompiledDoubleFunction::operator()(const double *arg) const
|
|||||||
{
|
{
|
||||||
double result;
|
double result;
|
||||||
|
|
||||||
for (Index i = 0; i < getNArg(); ++i)
|
compile();
|
||||||
|
for (unsigned int i = 0; i < getNArg(); ++i)
|
||||||
{
|
{
|
||||||
context_->vTable["x_" + strFrom(i)] = arg[i];
|
context_->vMem[(*varAddress_)[i]] = arg[i];
|
||||||
}
|
}
|
||||||
(*interpreter_)(*context_);
|
(*interpreter_)(*context_);
|
||||||
if (!context_->dStack.empty())
|
if (!context_->dStack.empty())
|
||||||
@ -74,7 +91,7 @@ double CompiledDoubleFunction::operator()(const double *arg) const
|
|||||||
// IO //////////////////////////////////////////////////////////////////////////
|
// IO //////////////////////////////////////////////////////////////////////////
|
||||||
ostream & Latan::operator<<(ostream &out, CompiledDoubleFunction &f)
|
ostream & Latan::operator<<(ostream &out, CompiledDoubleFunction &f)
|
||||||
{
|
{
|
||||||
f.interpreter_->compile();
|
f.compile();
|
||||||
out << *(f.interpreter_);
|
out << *(f.interpreter_);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
@ -46,8 +46,13 @@ public:
|
|||||||
friend std::ostream & operator<<(std::ostream &out,
|
friend std::ostream & operator<<(std::ostream &out,
|
||||||
CompiledDoubleFunction &f);
|
CompiledDoubleFunction &f);
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<MathInterpreter> interpreter_;
|
// compile
|
||||||
std::shared_ptr<RunContext> context_;
|
void compile(void) const;
|
||||||
|
private:
|
||||||
|
std::shared_ptr<MathInterpreter> interpreter_;
|
||||||
|
std::shared_ptr<RunContext> context_;
|
||||||
|
std::shared_ptr<std::vector<unsigned int>> varAddress_;
|
||||||
|
std::shared_ptr<bool> isCompiled_;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream & operator<<(std::ostream &out, CompiledDoubleFunction &f);
|
std::ostream & operator<<(std::ostream &out, CompiledDoubleFunction &f);
|
||||||
|
@ -46,7 +46,29 @@ void CompiledDoubleModel::setCode(const std::string &code)
|
|||||||
{
|
{
|
||||||
interpreter_.reset(new MathInterpreter(code));
|
interpreter_.reset(new MathInterpreter(code));
|
||||||
context_.reset(new RunContext);
|
context_.reset(new RunContext);
|
||||||
StdMath::addStdMathFunc(context_->fTable);
|
varAddress_.reset(new std::vector<unsigned int>);
|
||||||
|
parAddress_.reset(new std::vector<unsigned int>);
|
||||||
|
isCompiled_.reset(new bool(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
// compile /////////////////////////////////////////////////////////////////////
|
||||||
|
void CompiledDoubleModel::compile(void) const
|
||||||
|
{
|
||||||
|
if (!*isCompiled_)
|
||||||
|
{
|
||||||
|
interpreter_->compile(*(context_));
|
||||||
|
varAddress_->clear();
|
||||||
|
parAddress_->clear();
|
||||||
|
for (Index i = 0; i < getNArg(); ++i)
|
||||||
|
{
|
||||||
|
varAddress_->push_back(context_->vTable.at("x_" + strFrom(i)));
|
||||||
|
}
|
||||||
|
for (Index j = 0; j < getNPar(); ++j)
|
||||||
|
{
|
||||||
|
parAddress_->push_back(context_->vTable.at("p_" + strFrom(j)));
|
||||||
|
}
|
||||||
|
*isCompiled_ = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// function call ///////////////////////////////////////////////////////////////
|
// function call ///////////////////////////////////////////////////////////////
|
||||||
@ -55,13 +77,14 @@ double CompiledDoubleModel::operator()(const double *arg,
|
|||||||
{
|
{
|
||||||
double result;
|
double result;
|
||||||
|
|
||||||
for (Index i = 0; i < getNArg(); ++i)
|
compile();
|
||||||
|
for (unsigned int i = 0; i < getNArg(); ++i)
|
||||||
{
|
{
|
||||||
context_->vTable["x_" + strFrom(i)] = arg[i];
|
context_->vMem[(*varAddress_)[i]] = arg[i];
|
||||||
}
|
}
|
||||||
for (Index j = 0; j < getNPar(); ++j)
|
for (unsigned int j = 0; j < getNPar(); ++j)
|
||||||
{
|
{
|
||||||
context_->vTable["p_" + strFrom(j)] = par[j];
|
context_->vMem[(*parAddress_)[j]] = par[j];
|
||||||
}
|
}
|
||||||
(*interpreter_)(*context_);
|
(*interpreter_)(*context_);
|
||||||
if (!context_->dStack.empty())
|
if (!context_->dStack.empty())
|
||||||
@ -81,7 +104,7 @@ double CompiledDoubleModel::operator()(const double *arg,
|
|||||||
// IO //////////////////////////////////////////////////////////////////////////
|
// IO //////////////////////////////////////////////////////////////////////////
|
||||||
ostream & Latan::operator<<(std::ostream &out, CompiledDoubleModel &m)
|
ostream & Latan::operator<<(std::ostream &out, CompiledDoubleModel &m)
|
||||||
{
|
{
|
||||||
m.interpreter_->compile();
|
m.compile();
|
||||||
out << *(m.interpreter_);
|
out << *(m.interpreter_);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
@ -48,8 +48,13 @@ public:
|
|||||||
friend std::ostream & operator<<(std::ostream &out,
|
friend std::ostream & operator<<(std::ostream &out,
|
||||||
CompiledDoubleModel &f);
|
CompiledDoubleModel &f);
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<MathInterpreter> interpreter_;
|
// compile
|
||||||
std::shared_ptr<RunContext> context_;
|
void compile(void) const;
|
||||||
|
private:
|
||||||
|
std::shared_ptr<MathInterpreter> interpreter_;
|
||||||
|
std::shared_ptr<RunContext> context_;
|
||||||
|
std::shared_ptr<std::vector<unsigned int>> varAddress_, parAddress_;
|
||||||
|
std::shared_ptr<bool> isCompiled_;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream & operator<<(std::ostream &out, CompiledDoubleModel &f);
|
std::ostream & operator<<(std::ostream &out, CompiledDoubleModel &f);
|
||||||
|
60
lib/Math.cpp
60
lib/Math.cpp
@ -90,63 +90,3 @@ DEF_STD_FUNC_2ARG(fmin)
|
|||||||
|
|
||||||
// Absolute value
|
// Absolute value
|
||||||
DEF_STD_FUNC_1ARG(fabs)
|
DEF_STD_FUNC_1ARG(fabs)
|
||||||
|
|
||||||
#define ADD_FUNC(func) fTable[#func] = &STDMATH_NAMESPACE::func
|
|
||||||
void STDMATH_NAMESPACE::addStdMathFunc(FunctionTable &fTable)
|
|
||||||
{
|
|
||||||
// Trigonometric functions
|
|
||||||
ADD_FUNC(cos);
|
|
||||||
ADD_FUNC(sin);
|
|
||||||
ADD_FUNC(tan);
|
|
||||||
ADD_FUNC(acos);
|
|
||||||
ADD_FUNC(asin);
|
|
||||||
ADD_FUNC(atan);
|
|
||||||
ADD_FUNC(atan2);
|
|
||||||
|
|
||||||
// Hyperbolic functions
|
|
||||||
ADD_FUNC(cosh);
|
|
||||||
ADD_FUNC(sinh);
|
|
||||||
ADD_FUNC(tanh);
|
|
||||||
ADD_FUNC(acosh);
|
|
||||||
ADD_FUNC(asinh);
|
|
||||||
ADD_FUNC(atanh);
|
|
||||||
|
|
||||||
// Exponential and logarithmic functions
|
|
||||||
ADD_FUNC(exp);
|
|
||||||
ADD_FUNC(log);
|
|
||||||
ADD_FUNC(log10);
|
|
||||||
ADD_FUNC(exp2);
|
|
||||||
ADD_FUNC(expm1);
|
|
||||||
ADD_FUNC(log1p);
|
|
||||||
ADD_FUNC(log2);
|
|
||||||
|
|
||||||
// Power functions
|
|
||||||
ADD_FUNC(pow);
|
|
||||||
ADD_FUNC(sqrt);
|
|
||||||
ADD_FUNC(cbrt);
|
|
||||||
ADD_FUNC(hypot);
|
|
||||||
|
|
||||||
// Error and gamma functions
|
|
||||||
ADD_FUNC(erf);
|
|
||||||
ADD_FUNC(erfc);
|
|
||||||
ADD_FUNC(tgamma);
|
|
||||||
ADD_FUNC(lgamma);
|
|
||||||
|
|
||||||
// Rounding and remainder functions
|
|
||||||
ADD_FUNC(ceil);
|
|
||||||
ADD_FUNC(floor);
|
|
||||||
ADD_FUNC(fmod);
|
|
||||||
ADD_FUNC(trunc);
|
|
||||||
ADD_FUNC(round);
|
|
||||||
ADD_FUNC(rint);
|
|
||||||
ADD_FUNC(nearbyint);
|
|
||||||
ADD_FUNC(remainder);
|
|
||||||
|
|
||||||
// Minimum, maximum, difference functions
|
|
||||||
ADD_FUNC(fdim);
|
|
||||||
ADD_FUNC(fmax);
|
|
||||||
ADD_FUNC(fmin);
|
|
||||||
|
|
||||||
// Absolute value
|
|
||||||
ADD_FUNC(fabs);
|
|
||||||
}
|
|
||||||
|
@ -95,9 +95,6 @@ DECL_STD_FUNC(fabs)
|
|||||||
|
|
||||||
namespace STDMATH_NAMESPACE
|
namespace STDMATH_NAMESPACE
|
||||||
{
|
{
|
||||||
// Add standard math functions to a table for the math compiler
|
|
||||||
void addStdMathFunc(FunctionTable &fTable);
|
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const double pi = 3.1415926535897932384626433832795028841970;
|
const double pi = 3.1415926535897932384626433832795028841970;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <LatAnalyze/MathInterpreter.hpp>
|
#include <LatAnalyze/MathInterpreter.hpp>
|
||||||
#include <LatAnalyze/includes.hpp>
|
#include <LatAnalyze/includes.hpp>
|
||||||
|
#include <LatAnalyze/Math.hpp>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Latan;
|
using namespace Latan;
|
||||||
@ -41,12 +42,14 @@ ostream &Latan::operator<<(ostream& out, const Instruction& ins)
|
|||||||
Push::Push(const double val)
|
Push::Push(const double val)
|
||||||
: type_(ArgType::Constant)
|
: type_(ArgType::Constant)
|
||||||
, val_(val)
|
, val_(val)
|
||||||
|
, address_(0)
|
||||||
, name_("")
|
, name_("")
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Push::Push(const string &name)
|
Push::Push(const unsigned int address, const string &name)
|
||||||
: type_(ArgType::Variable)
|
: type_(ArgType::Variable)
|
||||||
, val_(0.0)
|
, val_(0.0)
|
||||||
|
, address_(address)
|
||||||
, name_(name)
|
, name_(name)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -61,7 +64,7 @@ void Push::operator()(RunContext &context) const
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
context.dStack.push(context.vTable.at(name_));
|
context.dStack.push(context.vMem[address_]);
|
||||||
}
|
}
|
||||||
catch (out_of_range)
|
catch (out_of_range)
|
||||||
{
|
{
|
||||||
@ -81,13 +84,14 @@ void Push::print(ostream &out) const
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out << CODE_MOD << name_;
|
out << CODE_MOD << name_ << " @v" << address_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pop constructor /////////////////////////////////////////////////////////////
|
// Pop constructor /////////////////////////////////////////////////////////////
|
||||||
Pop::Pop(const string &name)
|
Pop::Pop(const unsigned int address, const string &name)
|
||||||
: name_(name)
|
: address_(address)
|
||||||
|
, name_(name)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// Pop execution ///////////////////////////////////////////////////////////////
|
// Pop execution ///////////////////////////////////////////////////////////////
|
||||||
@ -95,7 +99,7 @@ void Pop::operator()(RunContext &context) const
|
|||||||
{
|
{
|
||||||
if (!name_.empty())
|
if (!name_.empty())
|
||||||
{
|
{
|
||||||
context.vTable[name_] = context.dStack.top();
|
context.vMem[address_] = context.dStack.top();
|
||||||
}
|
}
|
||||||
context.dStack.pop();
|
context.dStack.pop();
|
||||||
context.insIndex++;
|
context.insIndex++;
|
||||||
@ -104,12 +108,13 @@ void Pop::operator()(RunContext &context) const
|
|||||||
// Pop print ///////////////////////////////////////////////////////////////////
|
// Pop print ///////////////////////////////////////////////////////////////////
|
||||||
void Pop::print(ostream &out) const
|
void Pop::print(ostream &out) const
|
||||||
{
|
{
|
||||||
out << CODE_MOD << "pop" << CODE_MOD << name_;
|
out << CODE_MOD << "pop" << CODE_MOD << name_ << " @v" << address_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store constructor ///////////////////////////////////////////////////////////
|
// Store constructor ///////////////////////////////////////////////////////////
|
||||||
Store::Store(const string &name)
|
Store::Store(const unsigned int address, const string &name)
|
||||||
: name_(name)
|
: address_(address)
|
||||||
|
, name_(name)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// Store execution /////////////////////////////////////////////////////////////
|
// Store execution /////////////////////////////////////////////////////////////
|
||||||
@ -117,7 +122,7 @@ void Store::operator()(RunContext &context) const
|
|||||||
{
|
{
|
||||||
if (!name_.empty())
|
if (!name_.empty())
|
||||||
{
|
{
|
||||||
context.vTable[name_] = context.dStack.top();
|
context.vMem[address_] = context.dStack.top();
|
||||||
}
|
}
|
||||||
context.insIndex++;
|
context.insIndex++;
|
||||||
}
|
}
|
||||||
@ -125,12 +130,13 @@ void Store::operator()(RunContext &context) const
|
|||||||
// Store print /////////////////////////////////////////////////////////////////
|
// Store print /////////////////////////////////////////////////////////////////
|
||||||
void Store::print(ostream &out) const
|
void Store::print(ostream &out) const
|
||||||
{
|
{
|
||||||
out << CODE_MOD << "store" << CODE_MOD << name_;
|
out << CODE_MOD << "store" << CODE_MOD << name_ << " @v" << address_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call constructor ////////////////////////////////////////////////////////////
|
// Call constructor ////////////////////////////////////////////////////////////
|
||||||
Call::Call(const string &name)
|
Call::Call(const unsigned int address, const string &name)
|
||||||
: name_(name)
|
: address_(address)
|
||||||
|
, name_(name)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// Call execution //////////////////////////////////////////////////////////////
|
// Call execution //////////////////////////////////////////////////////////////
|
||||||
@ -138,7 +144,7 @@ void Call::operator()(RunContext &context) const
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
context.dStack.push((*context.fTable.at(name_))(context.dStack));
|
context.dStack.push((*context.fMem[address_])(context.dStack));
|
||||||
}
|
}
|
||||||
catch (out_of_range)
|
catch (out_of_range)
|
||||||
{
|
{
|
||||||
@ -150,7 +156,7 @@ void Call::operator()(RunContext &context) const
|
|||||||
// Call print //////////////////////////////////////////////////////////////////
|
// Call print //////////////////////////////////////////////////////////////////
|
||||||
void Call::print(ostream &out) const
|
void Call::print(ostream &out) const
|
||||||
{
|
{
|
||||||
out << CODE_MOD << "call" << CODE_MOD << name_;
|
out << CODE_MOD << "call" << CODE_MOD << name_ << " @f" << address_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Math operations /////////////////////////////////////////////////////////////
|
// Math operations /////////////////////////////////////////////////////////////
|
||||||
@ -263,23 +269,40 @@ ostream &Latan::operator<<(ostream &out, const ExprNode &n)
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PUSH_INS(program, type, ...) \
|
#define PUSH_INS(program, type, ...)\
|
||||||
program.push_back(unique_ptr<type>(new type(__VA_ARGS__)))
|
program.push_back(unique_ptr<type>(new type(__VA_ARGS__)))
|
||||||
|
#define GET_ADDRESS(address, table, name)\
|
||||||
|
try\
|
||||||
|
{\
|
||||||
|
address = (table).at(name);\
|
||||||
|
}\
|
||||||
|
catch (out_of_range)\
|
||||||
|
{\
|
||||||
|
address = static_cast<unsigned int>((table).size());\
|
||||||
|
(table)[(name)] = address;\
|
||||||
|
}\
|
||||||
|
|
||||||
// VarNode compile /////////////////////////////////////////////////////////////
|
// VarNode compile /////////////////////////////////////////////////////////////
|
||||||
void VarNode::compile(Program &program) const
|
void VarNode::compile(Program &program, AddressTable &vTable,
|
||||||
|
AddressTable &fTable __unused) const
|
||||||
{
|
{
|
||||||
PUSH_INS(program, Push, getName());
|
unsigned int address;
|
||||||
|
|
||||||
|
GET_ADDRESS(address, vTable, getName());
|
||||||
|
PUSH_INS(program, Push, address, getName());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CstNode compile /////////////////////////////////////////////////////////////
|
// CstNode compile /////////////////////////////////////////////////////////////
|
||||||
void CstNode::compile(Program &program) const
|
void CstNode::compile(Program &program, AddressTable &nextVAddress __unused,
|
||||||
|
AddressTable &nextFAddress __unused) const
|
||||||
{
|
{
|
||||||
PUSH_INS(program, Push, strTo<double>(getName()));
|
PUSH_INS(program, Push, strTo<double>(getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// SemicolonNode compile ///////////////////////////////////////////////////////
|
// SemicolonNode compile ///////////////////////////////////////////////////////
|
||||||
void SemicolonNode::compile(Program &program) const
|
void SemicolonNode::compile(Program &program, AddressTable &vTable,
|
||||||
|
AddressTable &fTable) const
|
||||||
{
|
{
|
||||||
auto &n = *this;
|
auto &n = *this;
|
||||||
|
|
||||||
@ -291,28 +314,31 @@ void SemicolonNode::compile(Program &program) const
|
|||||||
|
|
||||||
if (isAssign||isSemiColumn||isKeyword)
|
if (isAssign||isSemiColumn||isKeyword)
|
||||||
{
|
{
|
||||||
n[i].compile(program);
|
n[i].compile(program, vTable, fTable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssignNode compile //////////////////////////////////////////////////////////
|
// AssignNode compile //////////////////////////////////////////////////////////
|
||||||
void AssignNode::compile(Program &program) const
|
void AssignNode::compile(Program &program, AddressTable &vTable,
|
||||||
|
AddressTable &fTable) const
|
||||||
{
|
{
|
||||||
auto &n = *this;
|
auto &n = *this;
|
||||||
|
|
||||||
if (isDerivedFrom<VarNode>(&n[0]))
|
if (isDerivedFrom<VarNode>(&n[0]))
|
||||||
{
|
{
|
||||||
bool hasSemicolonParent = isDerivedFrom<SemicolonNode>(getParent());
|
bool hasSemicolonParent = isDerivedFrom<SemicolonNode>(getParent());
|
||||||
|
unsigned int address;
|
||||||
|
|
||||||
n[1].compile(program);
|
n[1].compile(program, vTable, fTable);
|
||||||
|
GET_ADDRESS(address, vTable, n[0].getName());
|
||||||
if (hasSemicolonParent)
|
if (hasSemicolonParent)
|
||||||
{
|
{
|
||||||
PUSH_INS(program, Pop, n[0].getName());
|
PUSH_INS(program, Pop, address, n[0].getName());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PUSH_INS(program, Store, n[0].getName());
|
PUSH_INS(program, Store, address, n[0].getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -326,13 +352,14 @@ void AssignNode::compile(Program &program) const
|
|||||||
#define ELIFNODE(name, nArg) else IFNODE(name, nArg)
|
#define ELIFNODE(name, nArg) else IFNODE(name, nArg)
|
||||||
#define ELSE else
|
#define ELSE else
|
||||||
|
|
||||||
void MathOpNode::compile(Program &program) const
|
void MathOpNode::compile(Program &program, AddressTable &vTable,
|
||||||
|
AddressTable &fTable) const
|
||||||
{
|
{
|
||||||
auto &n = *this;
|
auto &n = *this;
|
||||||
|
|
||||||
for (Index i = 0; i < n.getNArg(); ++i)
|
for (Index i = 0; i < n.getNArg(); ++i)
|
||||||
{
|
{
|
||||||
n[i].compile(program);
|
n[i].compile(program, vTable, fTable);
|
||||||
}
|
}
|
||||||
IFNODE("-", 1) PUSH_INS(program, Neg,);
|
IFNODE("-", 1) PUSH_INS(program, Neg,);
|
||||||
ELIFNODE("+", 2) PUSH_INS(program, Add,);
|
ELIFNODE("+", 2) PUSH_INS(program, Add,);
|
||||||
@ -344,23 +371,27 @@ void MathOpNode::compile(Program &program) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FuncNode compile ////////////////////////////////////////////////////////////
|
// FuncNode compile ////////////////////////////////////////////////////////////
|
||||||
void FuncNode::compile(Program &program) const
|
void FuncNode::compile(Program &program, AddressTable &vTable,
|
||||||
|
AddressTable &fTable) const
|
||||||
{
|
{
|
||||||
auto &n = *this;
|
auto &n = *this;
|
||||||
|
unsigned int address;
|
||||||
|
|
||||||
for (Index i = 0; i < n.getNArg(); ++i)
|
for (Index i = 0; i < n.getNArg(); ++i)
|
||||||
{
|
{
|
||||||
n[i].compile(program);
|
n[i].compile(program, vTable, fTable);
|
||||||
}
|
}
|
||||||
PUSH_INS(program, Call, getName());
|
GET_ADDRESS(address, fTable, getName());
|
||||||
|
PUSH_INS(program, Call, address, getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReturnNode compile ////////////////////////////////////////////////////////////
|
// ReturnNode compile ////////////////////////////////////////////////////////////
|
||||||
void ReturnNode::compile(Program &program) const
|
void ReturnNode::compile(Program &program, AddressTable &vTable,
|
||||||
|
AddressTable &fTable) const
|
||||||
{
|
{
|
||||||
auto &n = *this;
|
auto &n = *this;
|
||||||
|
|
||||||
n[0].compile(program);
|
n[0].compile(program, vTable, fTable);
|
||||||
program.push_back(nullptr);
|
program.push_back(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,7 +470,57 @@ void MathInterpreter::parse(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// interpreter /////////////////////////////////////////////////////////////////
|
// interpreter /////////////////////////////////////////////////////////////////
|
||||||
void MathInterpreter::compile(void)
|
#define ADD_FUNC(context, func)\
|
||||||
|
try\
|
||||||
|
{\
|
||||||
|
(context).fMem[(context).fTable.at(#func)] = &STDMATH_NAMESPACE::func;\
|
||||||
|
}\
|
||||||
|
catch (out_of_range)\
|
||||||
|
{}
|
||||||
|
|
||||||
|
#define ADD_STDMATH_FUNCS(context)\
|
||||||
|
ADD_FUNC(context, cos);\
|
||||||
|
ADD_FUNC(context, sin);\
|
||||||
|
ADD_FUNC(context, tan);\
|
||||||
|
ADD_FUNC(context, acos);\
|
||||||
|
ADD_FUNC(context, asin);\
|
||||||
|
ADD_FUNC(context, atan);\
|
||||||
|
ADD_FUNC(context, atan2);\
|
||||||
|
ADD_FUNC(context, cosh);\
|
||||||
|
ADD_FUNC(context, sinh);\
|
||||||
|
ADD_FUNC(context, tanh);\
|
||||||
|
ADD_FUNC(context, acosh);\
|
||||||
|
ADD_FUNC(context, asinh);\
|
||||||
|
ADD_FUNC(context, atanh);\
|
||||||
|
ADD_FUNC(context, exp);\
|
||||||
|
ADD_FUNC(context, log);\
|
||||||
|
ADD_FUNC(context, log10);\
|
||||||
|
ADD_FUNC(context, exp2);\
|
||||||
|
ADD_FUNC(context, expm1);\
|
||||||
|
ADD_FUNC(context, log1p);\
|
||||||
|
ADD_FUNC(context, log2);\
|
||||||
|
ADD_FUNC(context, pow);\
|
||||||
|
ADD_FUNC(context, sqrt);\
|
||||||
|
ADD_FUNC(context, cbrt);\
|
||||||
|
ADD_FUNC(context, hypot);\
|
||||||
|
ADD_FUNC(context, erf);\
|
||||||
|
ADD_FUNC(context, erfc);\
|
||||||
|
ADD_FUNC(context, tgamma);\
|
||||||
|
ADD_FUNC(context, lgamma);\
|
||||||
|
ADD_FUNC(context, ceil);\
|
||||||
|
ADD_FUNC(context, floor);\
|
||||||
|
ADD_FUNC(context, fmod);\
|
||||||
|
ADD_FUNC(context, trunc);\
|
||||||
|
ADD_FUNC(context, round);\
|
||||||
|
ADD_FUNC(context, rint);\
|
||||||
|
ADD_FUNC(context, nearbyint);\
|
||||||
|
ADD_FUNC(context, remainder);\
|
||||||
|
ADD_FUNC(context, fdim);\
|
||||||
|
ADD_FUNC(context, fmax);\
|
||||||
|
ADD_FUNC(context, fmin);\
|
||||||
|
ADD_FUNC(context, fabs);
|
||||||
|
|
||||||
|
void MathInterpreter::compile(RunContext &context)
|
||||||
{
|
{
|
||||||
bool gotReturn = false;
|
bool gotReturn = false;
|
||||||
|
|
||||||
@ -449,34 +530,43 @@ void MathInterpreter::compile(void)
|
|||||||
status_ |= Status::parsed;
|
status_ |= Status::parsed;
|
||||||
status_ -= status_ & Status::compiled;
|
status_ -= status_ & Status::compiled;
|
||||||
}
|
}
|
||||||
if (root_)
|
if (!(status_ & Status::compiled))
|
||||||
{
|
{
|
||||||
root_->compile(program_);
|
if (root_)
|
||||||
for (unsigned int i = 0; i < program_.size(); ++i)
|
|
||||||
{
|
{
|
||||||
if (!program_[i])
|
context.vTable.clear();
|
||||||
|
context.fTable.clear();
|
||||||
|
root_->compile(program_, context.vTable, context.fTable);
|
||||||
|
for (unsigned int i = 0; i < program_.size(); ++i)
|
||||||
{
|
{
|
||||||
gotReturn = true;
|
if (!program_[i])
|
||||||
program_.resize(i);
|
{
|
||||||
program_.shrink_to_fit();
|
gotReturn = true;
|
||||||
break;
|
program_.resize(i);
|
||||||
|
program_.shrink_to_fit();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
context.vMem.resize(context.vTable.size());
|
||||||
|
context.fMem.resize(context.fTable.size());
|
||||||
|
ADD_STDMATH_FUNCS(context);
|
||||||
}
|
}
|
||||||
|
if (!root_||!gotReturn)
|
||||||
|
{
|
||||||
|
LATAN_ERROR(Syntax, "expected 'return' in program '" + codeName_
|
||||||
|
+ "'");
|
||||||
|
}
|
||||||
|
status_ |= Status::compiled;
|
||||||
}
|
}
|
||||||
if (!root_||!gotReturn)
|
|
||||||
{
|
|
||||||
LATAN_ERROR(Syntax, "expected 'return' in program '" + codeName_ + "'");
|
|
||||||
}
|
|
||||||
status_ |= Status::compiled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// execution ///////////////////////////////////////////////////////////////////
|
// execution ///////////////////////////////////////////////////////////////////
|
||||||
void MathInterpreter::operator()(RunContext &context)
|
void MathInterpreter::operator()(RunContext &context)
|
||||||
{
|
{
|
||||||
if (!(status_ & Status::compiled))
|
if (!(status_ & Status::compiled))
|
||||||
{
|
{
|
||||||
compile();
|
compile(context);
|
||||||
}
|
}
|
||||||
execute(context);
|
execute(context);
|
||||||
}
|
}
|
||||||
|
@ -36,15 +36,15 @@ BEGIN_NAMESPACE
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Instruction classes *
|
* Instruction classes *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
typedef std::map<std::string, double> VarTable;
|
typedef std::map<std::string, unsigned int> AddressTable;
|
||||||
typedef std::map<std::string, DoubleFunction *> FunctionTable;
|
|
||||||
|
|
||||||
struct RunContext
|
struct RunContext
|
||||||
{
|
{
|
||||||
unsigned int insIndex;
|
unsigned int insIndex;
|
||||||
std::stack<double> dStack;
|
std::stack<double> dStack;
|
||||||
VarTable vTable;
|
std::vector<double> vMem;
|
||||||
FunctionTable fTable;
|
std::vector<DoubleFunction *> fMem;
|
||||||
|
AddressTable vTable, fTable;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Abstract base
|
// Abstract base
|
||||||
@ -77,15 +77,16 @@ private:
|
|||||||
public:
|
public:
|
||||||
//constructors
|
//constructors
|
||||||
explicit Push(const double val);
|
explicit Push(const double val);
|
||||||
explicit Push(const std::string &name);
|
explicit Push(const unsigned int address, const std::string &name);
|
||||||
// instruction execution
|
// instruction execution
|
||||||
virtual void operator()(RunContext &context) const;
|
virtual void operator()(RunContext &context) const;
|
||||||
private:
|
private:
|
||||||
virtual void print(std::ostream& out) const;
|
virtual void print(std::ostream& out) const;
|
||||||
private:
|
private:
|
||||||
ArgType type_;
|
ArgType type_;
|
||||||
double val_;
|
double val_;
|
||||||
std::string name_;
|
unsigned int address_;
|
||||||
|
std::string name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pop
|
// Pop
|
||||||
@ -93,12 +94,13 @@ class Pop: public Instruction
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//constructor
|
//constructor
|
||||||
explicit Pop(const std::string &name);
|
explicit Pop(const unsigned int address, const std::string &name);
|
||||||
// instruction execution
|
// instruction execution
|
||||||
virtual void operator()(RunContext &context) const;
|
virtual void operator()(RunContext &context) const;
|
||||||
private:
|
private:
|
||||||
virtual void print(std::ostream& out) const;
|
virtual void print(std::ostream& out) const;
|
||||||
private:
|
private:
|
||||||
|
unsigned int address_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -107,12 +109,13 @@ class Store: public Instruction
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//constructor
|
//constructor
|
||||||
explicit Store(const std::string &name);
|
explicit Store(const unsigned int address, const std::string &name);
|
||||||
// instruction execution
|
// instruction execution
|
||||||
virtual void operator()(RunContext &context) const;
|
virtual void operator()(RunContext &context) const;
|
||||||
private:
|
private:
|
||||||
virtual void print(std::ostream& out) const;
|
virtual void print(std::ostream& out) const;
|
||||||
private:
|
private:
|
||||||
|
unsigned int address_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -121,12 +124,13 @@ class Call: public Instruction
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//constructor
|
//constructor
|
||||||
explicit Call(const std::string &name);
|
explicit Call(const unsigned int address, const std::string &name);
|
||||||
// instruction execution
|
// instruction execution
|
||||||
virtual void operator()(RunContext &context) const;
|
virtual void operator()(RunContext &context) const;
|
||||||
private:
|
private:
|
||||||
virtual void print(std::ostream& out) const;
|
virtual void print(std::ostream& out) const;
|
||||||
private:
|
private:
|
||||||
|
unsigned int address_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -167,7 +171,8 @@ public:
|
|||||||
// operator
|
// operator
|
||||||
const ExprNode &operator[](const Index i) const;
|
const ExprNode &operator[](const Index i) const;
|
||||||
// compile
|
// compile
|
||||||
virtual void compile(Program &program) const = 0;
|
virtual void compile(Program &program, AddressTable &vTable,
|
||||||
|
AddressTable &fTable) const = 0;
|
||||||
private:
|
private:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
std::vector<std::unique_ptr<ExprNode>> arg_;
|
std::vector<std::unique_ptr<ExprNode>> arg_;
|
||||||
@ -181,7 +186,8 @@ class name: public base\
|
|||||||
{\
|
{\
|
||||||
public:\
|
public:\
|
||||||
using base::base;\
|
using base::base;\
|
||||||
virtual void compile(Program &program) const;\
|
virtual void compile(Program &program, AddressTable &vTable,\
|
||||||
|
AddressTable &fTable) const;\
|
||||||
}
|
}
|
||||||
|
|
||||||
DECL_NODE(ExprNode, VarNode);
|
DECL_NODE(ExprNode, VarNode);
|
||||||
@ -195,7 +201,8 @@ class KeywordNode: public ExprNode
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ExprNode::ExprNode;
|
using ExprNode::ExprNode;
|
||||||
virtual void compile(Program &program) const = 0;
|
virtual void compile(Program &program, AddressTable &vTable,
|
||||||
|
AddressTable &fTable) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
DECL_NODE(KeywordNode, ReturnNode);
|
DECL_NODE(KeywordNode, ReturnNode);
|
||||||
@ -245,7 +252,7 @@ public:
|
|||||||
// initialization
|
// initialization
|
||||||
void setCode(const std::string &code);
|
void setCode(const std::string &code);
|
||||||
// interpreter
|
// interpreter
|
||||||
void compile(void);
|
void compile(RunContext &context);
|
||||||
// execution
|
// execution
|
||||||
void operator()(RunContext &context);
|
void operator()(RunContext &context);
|
||||||
// IO
|
// IO
|
||||||
|
Loading…
x
Reference in New Issue
Block a user