diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index a41a9e44c..fc217e225 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -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; }; diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 461d4522d..e3ec1410a 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -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)); } diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 9f96e0029..5aebf641d 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -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)); } diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index c5d04185e..a59be95e9 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -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); } ; %% diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index d77802521..884573a37 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -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 { diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index e4040a00b..67776cfe5 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -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)); } diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index 2bd97dd34..2975d2e82 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -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)); } diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 5395b1cee..7495c3161 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -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)); }