[poincare] Enable functions with more than one argument

Change-Id: I543594072c37716fffcc54d5d6ba9b6b3499bcd1
This commit is contained in:
Émilie Feral
2017-01-03 17:21:52 +01:00
parent 1efb46e6ce
commit 628c5a91ca
8 changed files with 53 additions and 35 deletions

View File

@@ -10,14 +10,15 @@ class Function : public Expression {
public:
Function(const char * name);
~Function();
void setArgument(Expression * arg, bool clone = true);
void setArgument(Expression ** args, int numberOfArguments, bool clone = true);
ExpressionLayout * createLayout() const override;
const Expression * operand(int i) const override;
int numberOfOperands() const override;
Expression * clone() const override;
Expression * evaluate(Context& context) const override;
protected:
const Expression * m_arg;
Expression ** m_args;
int m_numberOfArguments;
private:
const char * m_name;
};

View File

@@ -18,11 +18,11 @@ Expression * AbsoluteValue::cloneWithDifferentOperands(Expression** newOperands,
int numberOfOperands, bool cloneOperands) const {
assert(numberOfOperands == 1);
assert(newOperands != nullptr);
AbsoluteValue * c = new AbsoluteValue();
c->setArgument(*newOperands, cloneOperands);
return c;
AbsoluteValue * a = new AbsoluteValue();
a->setArgument(newOperands, numberOfOperands, cloneOperands);
return a;
}
float AbsoluteValue::approximate(Context& context) const {
return fabsf(m_arg->approximate(context));
return fabsf(m_args[0]->approximate(context));
}

View File

@@ -19,10 +19,10 @@ Expression * Cosine::cloneWithDifferentOperands(Expression** newOperands,
assert(numberOfOperands == 1);
assert(newOperands != nullptr);
Cosine * c = new Cosine();
c->setArgument(*newOperands, cloneOperands);
c->setArgument(newOperands, numberOfOperands, cloneOperands);
return c;
}
float Cosine::approximate(Context& context) const {
return cosf(m_arg->approximate(context));
return cosf(m_args[0]->approximate(context));
}

View File

@@ -121,7 +121,7 @@ exp:
| exp POW exp { Expression * terms[2] = {$1,$3}; $$ = new Power(terms, false); }
| LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Parenthesis($2, false); }
| LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = new Matrix($2); }
| FUNCTION LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = $1; $1->setArgument($3, false); }
| FUNCTION LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = $1; Expression * terms[1] = {$3}; $1->setArgument(terms, 1, false); }
;
%%

View File

@@ -8,48 +8,65 @@ extern "C" {
#include "layout/string_layout.h"
Function::Function(const char * name) :
m_arg(nullptr),
m_args(nullptr),
m_numberOfArguments(0),
m_name(name)
{
}
void Function::setArgument(Expression * arg, bool clone) {
if (m_arg != nullptr) {
delete m_arg;
void Function::setArgument(Expression ** args, int numberOfArguments, bool clone) {
if (m_args != nullptr) {
for (int i = 0; i < m_numberOfArguments; i++) {
delete m_args[i];
}
free(m_args);
}
if (clone) {
m_arg = arg->clone();
} else {
m_arg = arg;
m_numberOfArguments = numberOfArguments;
m_args = (Expression **)malloc(numberOfArguments*sizeof(Expression *));
for (int i = 0; i < numberOfArguments; i++) {
assert(args[i] != nullptr);
if (clone) {
m_args[i] = args[i]->clone();
} else {
m_args[i] = args[i];
}
}
}
Function::~Function() {
if (m_arg != nullptr) {
delete m_arg;
if (m_args != nullptr) {
for (int i = 0; i < m_numberOfArguments; i++) {
delete m_args[i];
}
free(m_args);
}
}
Expression * Function::clone() const {
return this->cloneWithDifferentOperands((Expression**)&m_arg, 1, true);
return this->cloneWithDifferentOperands(m_args, m_numberOfArguments, true);
}
ExpressionLayout * Function::createLayout() const {
ExpressionLayout ** childrenLayouts = (ExpressionLayout **)malloc(4*sizeof(ExpressionLayout *));
ExpressionLayout ** childrenLayouts = (ExpressionLayout **)malloc((2*m_numberOfArguments+2)*sizeof(ExpressionLayout *));
childrenLayouts[0] = new StringLayout(m_name, strlen(m_name));
childrenLayouts[1] = new StringLayout("(", 1);
childrenLayouts[2] = m_arg->createLayout();
childrenLayouts[3] = new StringLayout(")", 1);
return new HorizontalLayout(childrenLayouts, 4);
int layoutIndex = 2;
childrenLayouts[layoutIndex++] = m_args[0]->createLayout();
for (int i = 1; i < m_numberOfArguments; i++) {
childrenLayouts[layoutIndex++] = new StringLayout(",", 1);
childrenLayouts[layoutIndex++] = m_args[i]->createLayout();
}
childrenLayouts[layoutIndex] = new StringLayout(")", 1);
return new HorizontalLayout(childrenLayouts, 2*m_numberOfArguments+2);
}
const Expression * Function::operand(int i) const {
assert(i==0);
return m_arg;
assert(i >= 0 && i < m_numberOfArguments);
return m_args[i];
}
int Function::numberOfOperands() const {
return 1;
return m_numberOfArguments;
}
Expression * Function::evaluate(Context& context) const {

View File

@@ -17,11 +17,11 @@ Expression * Logarithm::cloneWithDifferentOperands(Expression** newOperands,
int numberOfOperands, bool cloneOperands) const {
assert(numberOfOperands == 1);
assert(newOperands != nullptr);
Logarithm * c = new Logarithm();
c->setArgument(*newOperands, cloneOperands);
return c;
Logarithm * l = new Logarithm();
l->setArgument(newOperands, numberOfOperands, cloneOperands);
return l;
}
float Logarithm::approximate(Context& context) const {
return log10f(m_arg->approximate(context));
return log10f(m_args[0]->approximate(context));
}

View File

@@ -15,7 +15,7 @@ Expression * Sine::cloneWithDifferentOperands(Expression** newOperands,
assert(newOperands != nullptr);
assert(numberOfOperands == 1);
Sine * s = new Sine();
s->setArgument(*newOperands, cloneOperands);
s->setArgument(newOperands, numberOfOperands, cloneOperands);
return s;
}
@@ -24,5 +24,5 @@ Expression::Type Sine::type() const {
}
float Sine::approximate(Context& context) const {
return sinf(m_arg->approximate(context));
return sinf(m_args[0]->approximate(context));
}

View File

@@ -15,7 +15,7 @@ Expression * Tangent::cloneWithDifferentOperands(Expression** newOperands,
assert(newOperands != nullptr);
assert(numberOfOperands == 1);
Tangent * t = new Tangent();
t->setArgument(*newOperands, cloneOperands);
t->setArgument(newOperands, numberOfOperands, cloneOperands);
return t;
}
@@ -24,5 +24,5 @@ Expression::Type Tangent::type() const {
}
float Tangent::approximate(Context& context) const {
return tanf(m_arg->approximate(context));
return tanf(m_args[0]->approximate(context));
}