From d105236da91bebe4e91f029c017ccf0d4049b980 Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Thu, 24 Mar 2016 12:03:36 +0100 Subject: [PATCH 1/8] Add the Function and trig functions classes and layout. We create an abstraction for functions with the function class. Change-Id: Ia52f38da2ab3fb6781ad77c1b909676c53a4f424 --- poincare/Makefile | 7 ++- poincare/include/poincare.h | 6 +- poincare/include/poincare/cosinus.h | 13 ++++ poincare/include/poincare/expression.h | 5 +- poincare/include/poincare/function.h | 17 ++++++ poincare/include/poincare/sinus.h | 13 ++++ poincare/include/poincare/tangent.h | 13 ++++ poincare/src/cosinus.cpp | 11 ++++ poincare/src/expression_lexer.l | 3 + poincare/src/expression_parser.y | 6 ++ poincare/src/function.cpp | 10 ++++ poincare/src/layout/function_layout.cpp | 73 +++++++++++++++++++++++ poincare/src/layout/function_layout.h | 21 +++++++ poincare/src/layout/horizontal_layout.cpp | 2 +- poincare/src/sinus.cpp | 11 ++++ poincare/src/tangent.cpp | 11 ++++ 16 files changed, 218 insertions(+), 4 deletions(-) create mode 100644 poincare/include/poincare/cosinus.h create mode 100644 poincare/include/poincare/function.h create mode 100644 poincare/include/poincare/sinus.h create mode 100644 poincare/include/poincare/tangent.h create mode 100644 poincare/src/cosinus.cpp create mode 100644 poincare/src/function.cpp create mode 100644 poincare/src/layout/function_layout.cpp create mode 100644 poincare/src/layout/function_layout.h create mode 100644 poincare/src/sinus.cpp create mode 100644 poincare/src/tangent.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 788518f79..de32ca59a 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -4,23 +4,28 @@ objs += $(addprefix poincare/src/,\ binary_operation.o\ commutative_operation.o\ context.o\ + cosinus.o\ expression.o\ expression_lexer.o\ expression_parser.o\ float.o\ fraction.o\ + function.o\ integer.o\ leaf_expression.o\ power.o\ product.o\ + sinus.o\ subtraction.o\ symbol.o\ + tangent.o\ ) objs += $(addprefix poincare/src/layout/,\ + exponent_layout.o\ expression_layout.o\ fraction_layout.o\ + function_layout.o\ horizontal_layout.o\ - exponent_layout.o\ string_layout.o\ ) objs += $(addprefix poincare/src/simplify/,\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index eeaf014ef..4b89926c0 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -3,13 +3,17 @@ #include #include +#include #include -#include #include +#include +#include #include #include #include +#include #include #include +#include #endif diff --git a/poincare/include/poincare/cosinus.h b/poincare/include/poincare/cosinus.h new file mode 100644 index 000000000..5d4fc4e7a --- /dev/null +++ b/poincare/include/poincare/cosinus.h @@ -0,0 +1,13 @@ +#ifndef POINCARE_COSINUS_H +#define POINCARE_COSINUS_H + +#include + +class Cosinus : public Function { + public: + Cosinus(Expression * arg): Function(arg, (char*) "cos") {} + float approximate(Context& context) override; + Type type() override; +}; + +#endif diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 664ce6a64..af5e199f5 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -10,13 +10,16 @@ class Expression { public: enum class Type : uint8_t { Addition, + Cosinus, Float, Fraction, Integer, Power, Product, + Sinus, Subtraction, - Symbol + Symbol, + Tangent, }; static Expression * parse(char const * string); virtual ~Expression(); diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h new file mode 100644 index 000000000..2a8fa67fe --- /dev/null +++ b/poincare/include/poincare/function.h @@ -0,0 +1,17 @@ +#ifndef POINCARE_FUNCTION_H +#define POINCARE_FUNCTION_H + +#include + +class Function : public Expression { + public: + Function(Expression * arg, char* function_name): m_arg(arg), m_function_name(function_name) {} + ~Function(); + ExpressionLayout * createLayout(ExpressionLayout * parent) override; + protected: + Expression * m_arg; + private: + char* m_function_name; +}; + +#endif diff --git a/poincare/include/poincare/sinus.h b/poincare/include/poincare/sinus.h new file mode 100644 index 000000000..5378dd789 --- /dev/null +++ b/poincare/include/poincare/sinus.h @@ -0,0 +1,13 @@ +#ifndef POINCARE_SINUS_H +#define POINCARE_SINUS_H + +#include + +class Sinus : public Function { + public: + Sinus(Expression * arg): Function(arg, (char*) "sin") {} + float approximate(Context& context) override; + Type type() override; +}; + +#endif diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h new file mode 100644 index 000000000..f77593878 --- /dev/null +++ b/poincare/include/poincare/tangent.h @@ -0,0 +1,13 @@ +#ifndef POINCARE_TANGENT_H +#define POINCARE_TANGENT_H + +#include + +class Tangent : public Function { + public: + Tangent(Expression * arg): Function(arg, (char*) "tan") {} + float approximate(Context& context) override; + Type type() override; +}; + +#endif diff --git a/poincare/src/cosinus.cpp b/poincare/src/cosinus.cpp new file mode 100644 index 000000000..c21d00aa1 --- /dev/null +++ b/poincare/src/cosinus.cpp @@ -0,0 +1,11 @@ +#include +#include "layout/horizontal_layout.h" + +Expression::Type Cosinus::type() { + return Expression::Type::Cosinus; +} + +float Cosinus::approximate(Context& context) { + // FIXME: use cosinus obviously. + return m_arg->approximate(context); +} diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index 5dd2bb7b4..008e5fca5 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -43,6 +43,9 @@ class Expression; [0-9]+ { yylval->string = yytext; return(INTEGER); } [A-Za-z]+ { yylval->string = yytext; return(SYMBOL); } +sin {return(SINUS);} +cos {return(COSINUS);} +tan {return(TANGENT);} \+ { return(PLUS); } \- { return(MINUS); } \* { return(MULTIPLY); } diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index 505f1505b..bb3dd2b14 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -54,6 +54,9 @@ void poincare_expression_yyerror(void * scanner, Expression ** expressionOutput, %token MULTIPLY %token DIVIDE %token POW +%token SINUS +%token COSINUS +%token TANGENT %token LEFT_PARENTHESIS %token RIGHT_PARENTHESIS @@ -85,6 +88,9 @@ exp: | exp DIVIDE exp { Expression * terms[2] = {$1,$3}; $$ = new Fraction(terms, false); } | exp POW exp { Expression * terms[2] = {$1,$3}; $$ = new Power(terms, false); } | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = $2; } + | SINUS LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Sinus($3); } + | COSINUS LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Cosinus($3); } + | TANGENT LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Tangent($3); } ; %% diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp new file mode 100644 index 000000000..e7e230d11 --- /dev/null +++ b/poincare/src/function.cpp @@ -0,0 +1,10 @@ +#include +#include "layout/function_layout.h" + +Function::~Function() { + delete m_arg; +} + +ExpressionLayout * Function::createLayout(ExpressionLayout * parent) { + return new FunctionLayout(parent, m_function_name, m_arg); +} diff --git a/poincare/src/layout/function_layout.cpp b/poincare/src/layout/function_layout.cpp new file mode 100644 index 000000000..02bc5410b --- /dev/null +++ b/poincare/src/layout/function_layout.cpp @@ -0,0 +1,73 @@ +extern "C" { +#include +#include +} +#include "function_layout.h" +#include "string_layout.h" + +// This code seems like a duplicate of the horizontal layout but it isn't, indeed the horizontal +// layout is used to print the same operation applied to different expressions such that: +// "expr_1 + epr_2 + expr_3 + expr_4". +// Here we want the pattern +// FUNCTION_NAME(expr). +// Thus the code in horizontal layer is not really reusable. + +FunctionLayout::FunctionLayout(ExpressionLayout * parent, char* function_name, Expression * argument) : +ExpressionLayout(parent) { + m_children[0] = new StringLayout(this, function_name, 1); + + char string[2] = {'(', '\0'}; + m_children[1] = new StringLayout(this, string, 1); + + m_children[2] = argument->createLayout(this); + + string[0] = ')'; + m_children[3] = new StringLayout(this, string, 1); +} + +FunctionLayout::~FunctionLayout() { + for (int i(0); i<4; i++) { + delete m_children[i]; + } +} + +void FunctionLayout::render(KDPoint point) { } + +KDSize FunctionLayout::computeSize() { + KDSize size = (KDSize){.width = 0, .height = 0}; + int i = 0; + while (ExpressionLayout * c = child(i++)) { + KDSize childSize = c->size(); + size.width += childSize.width; + if (childSize.height > size.height) { + size.height = childSize.height; + } + } + return size; +} + +ExpressionLayout * FunctionLayout::child(uint16_t index) { + if (index >= 4) { + return nullptr; + } + return m_children[index]; +} + +KDPoint FunctionLayout::positionOfChild(ExpressionLayout * child) { + KDPoint position = (KDPoint){.x = 0, .y = 0}; + uint16_t index = 0; + for (int i=0;i<4;i++) { + if (m_children[i] == child) { + index = i; + break; + } + } + if (index > 0) { + ExpressionLayout * previousChild = m_children[index-1]; + assert(previousChild != nullptr); + position.x = previousChild->origin().x + previousChild->size().width; + } + position.y = (size().height - child->size().height)/2; + return position; +} + diff --git a/poincare/src/layout/function_layout.h b/poincare/src/layout/function_layout.h new file mode 100644 index 000000000..0b689dfcf --- /dev/null +++ b/poincare/src/layout/function_layout.h @@ -0,0 +1,21 @@ +#ifndef POINCARE_FUNCTION_LAYOUT_H +#define POINCARE_FUNCTION_LAYOUT_H + +#include +#include + +class FunctionLayout : public ExpressionLayout { + public: + FunctionLayout(ExpressionLayout * parent, char* function_name, Expression * arg); + ~FunctionLayout(); + protected: + void render(KDPoint point) override; + KDSize computeSize() override; + ExpressionLayout * child(uint16_t index) override; + KDPoint positionOfChild(ExpressionLayout * child) override; + private: + ExpressionLayout * m_children[4]; +}; + +#endif + diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index e1297a0d2..cc64c78af 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -6,7 +6,7 @@ extern "C" { #include "string_layout.h" HorizontalLayout::HorizontalLayout(ExpressionLayout * parent, Expression * left_expression, char symbol, Expression * right_expression) : -ExpressionLayout(parent ) { +ExpressionLayout(parent) { m_children[0] = left_expression->createLayout(this); char string[2] = {symbol, '\0'}; diff --git a/poincare/src/sinus.cpp b/poincare/src/sinus.cpp new file mode 100644 index 000000000..6e831cb2e --- /dev/null +++ b/poincare/src/sinus.cpp @@ -0,0 +1,11 @@ +#include +#include "layout/horizontal_layout.h" + +Expression::Type Sinus::type() { + return Expression::Type::Sinus; +} + +float Sinus::approximate(Context& context) { + // FIXME: use sinus obviously. + return m_arg->approximate(context); +} diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp new file mode 100644 index 000000000..71e9d3191 --- /dev/null +++ b/poincare/src/tangent.cpp @@ -0,0 +1,11 @@ +#include +#include "layout/horizontal_layout.h" + +Expression::Type Tangent::type() { + return Expression::Type::Tangent; +} + +float Tangent::approximate(Context& context) { + // FIXME: use tangent obviously. + return m_arg->approximate(context); +} From 3e632f5586b13681e0274bf9b08df76f87b1769e Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Thu, 24 Mar 2016 13:45:51 +0100 Subject: [PATCH 2/8] Rename text_input to utils, add a util in it. Change-Id: I5d37ed0a3a21e7d62aa061a6b09f30065c4cd8a6 --- app/Makefile | 2 +- app/app.cpp | 12 +----------- app/{text_input.cpp => utils.cpp} | 9 +++++++++ app/{text_input.h => utils.h} | 8 +++++--- 4 files changed, 16 insertions(+), 15 deletions(-) rename app/{text_input.cpp => utils.cpp} (92%) rename app/{text_input.h => utils.h} (61%) diff --git a/app/Makefile b/app/Makefile index fba1326d1..d662c1a4d 100644 --- a/app/Makefile +++ b/app/Makefile @@ -1,6 +1,6 @@ app_objs += $(addprefix app/,\ app.o\ - text_input.o) + utils.o) products += $(app_objs) app.elf app.hex app.bin app.elf: $(app_objs) diff --git a/app/app.cpp b/app/app.cpp index 043984995..eede4f5e7 100644 --- a/app/app.cpp +++ b/app/app.cpp @@ -6,7 +6,7 @@ extern "C" { #include -#include "text_input.h" +#include "utils.h" void draw_lines_from_center() { KDCoordinate width = SCREEN_WIDTH; @@ -60,16 +60,6 @@ void funnyPlot() { delete e; } -static void clear_screen() { - KDRect r; - r.x = 0; - r.y = 0; - r.width = SCREEN_WIDTH; - r.height = SCREEN_HEIGHT; - KDFillRect(r, 0x00); -} - - static void interactive_expression_parsing() { while (1) { char * text_input = get_text(); diff --git a/app/text_input.cpp b/app/utils.cpp similarity index 92% rename from app/text_input.cpp rename to app/utils.cpp index 522203310..f0e1c16d4 100644 --- a/app/text_input.cpp +++ b/app/utils.cpp @@ -7,6 +7,15 @@ extern "C" { #define PROMPT_HEIGHT 30 +void clear_screen() { + KDRect r; + r.x = 0; + r.y = 0; + r.width = SCREEN_WIDTH; + r.height = SCREEN_HEIGHT; + KDFillRect(r, 0x00); +} + static void clear_prompt() { KDRect r; r.x = 0; diff --git a/app/text_input.h b/app/utils.h similarity index 61% rename from app/text_input.h rename to app/utils.h index b7490c2ff..ca78fcae1 100644 --- a/app/text_input.h +++ b/app/utils.h @@ -1,8 +1,10 @@ -#ifndef APP_TEXTINPUT_H -#define APP_TEXTINPUT_H +#ifndef APP_UTILS_H +#define APP_UTILS_H /* Returns a pointer to an input text, allocated by the functions (it is thus * the caller's role to free it). */ char* get_text(); -#endif // APP_TEXTINPUT_H +void clear_screen(); + +#endif // APP_UTILS_H From 11537ef794296cfae944edbfa69775dcb9403241 Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Thu, 24 Mar 2016 13:53:54 +0100 Subject: [PATCH 3/8] Remove call to get_char to fix tests. Change-Id: I87e12b9ce5fc807edfcf1460e419bceed23474dd --- quiz/src/runner.c | 1 - 1 file changed, 1 deletion(-) diff --git a/quiz/src/runner.c b/quiz/src/runner.c index a19e202d8..bb76367cb 100644 --- a/quiz/src/runner.c +++ b/quiz/src/runner.c @@ -10,7 +10,6 @@ void print(char * message) { line_y += line_height; if (line_y > SCREEN_HEIGHT) { line_y = 0; - ion_getchar(); // Clear screen maybe? } } From f5f5399e92388b849112191c07b4b018a9303161 Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Thu, 24 Mar 2016 16:08:03 +0100 Subject: [PATCH 4/8] Horizontal layout Change-Id: Ie87dc14531e04b3577b691ae141d9b6a6d58a618 --- poincare/src/layout/horizontal_layout.cpp | 33 ++++++++++++----------- poincare/src/layout/horizontal_layout.h | 6 +++-- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index cc64c78af..0ba763f4b 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -5,25 +5,28 @@ extern "C" { #include "horizontal_layout.h" #include "string_layout.h" -HorizontalLayout::HorizontalLayout(ExpressionLayout * parent, Expression * left_expression, char symbol, Expression * right_expression) : -ExpressionLayout(parent) { - m_children[0] = left_expression->createLayout(this); - +HorizontalLayout::HorizontalLayout(ExpressionLayout * parent, int number_of_operands, Expression ** operands, char symbol) { + m_number_of_operands = number_of_operands; + // FIXME: This implementation is not optimal as the operator layout is created and stored a lot of times. + // The reason for this is how the layouts are drawn. + m_children_layouts = (ExpressionLayout **)malloc((2*m_number_of_operands-)*sizeof(ExpressionLayout *)); + m_operator_layout = new StringLayout(this, string, 1); char string[2] = {symbol, '\0'}; - m_children[1] = new StringLayout(this, string, 1); - - m_children[2] = right_expression->createLayout(this); + for (int i=1; icreateLayout(); + } } HorizontalLayout::~HorizontalLayout() { - delete m_children[2]; - delete m_children[1]; - delete m_children[0]; + for (int i(0); i= 3) { + if (index >= 2*m_number_of_operands) { return nullptr; } - return m_children[index]; + return m_children_layouts[index]; } KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index d4cb6a04a..4482aca87 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -6,7 +6,7 @@ class HorizontalLayout : public ExpressionLayout { public: - HorizontalLayout(ExpressionLayout * parent, Expression * left_expression, char symbol, Expression * right_expression); + HorizontalLayout(ExpressionLayout * parent, int number_of_operands, Expression ** operands, char symbol); ~HorizontalLayout(); protected: void render(KDPoint point) override; @@ -14,7 +14,9 @@ class HorizontalLayout : public ExpressionLayout { ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; private: - ExpressionLayout * m_children[3]; + int m_number_of_operands; + ExpressionLayout ** m_children_layouts; + ExpressionLayout * m_operator_layout; }; #endif From 4707459a19dd34bb71cb5766eb4864ae80aebf83 Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Thu, 24 Mar 2016 16:54:53 +0100 Subject: [PATCH 5/8] Update functions to use the clone interface. Change-Id: I6b4d6be5b1d963bc7d97851432e40844d3619d8d --- poincare/include/poincare/cosinus.h | 3 ++- poincare/include/poincare/function.h | 4 +++- poincare/include/poincare/sinus.h | 3 ++- poincare/include/poincare/tangent.h | 3 ++- poincare/src/cosinus.cpp | 4 ++++ poincare/src/function.cpp | 25 +++++++++++++++++++++++++ poincare/src/sinus.cpp | 4 ++++ poincare/src/tangent.cpp | 4 ++++ 8 files changed, 46 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/cosinus.h b/poincare/include/poincare/cosinus.h index 5d4fc4e7a..f23e66e4c 100644 --- a/poincare/include/poincare/cosinus.h +++ b/poincare/include/poincare/cosinus.h @@ -5,9 +5,10 @@ class Cosinus : public Function { public: - Cosinus(Expression * arg): Function(arg, (char*) "cos") {} + Cosinus(Expression * arg, bool clone_arg=true): Function(arg, (char*) "cos", clone_arg) {} float approximate(Context& context) override; Type type() override; + Expression * clone() override; }; #endif diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index 2a8fa67fe..e02e7e388 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -5,9 +5,11 @@ class Function : public Expression { public: - Function(Expression * arg, char* function_name): m_arg(arg), m_function_name(function_name) {} + Function(Expression * arg, char* function_name, bool clone_operands=true); ~Function(); ExpressionLayout * createLayout(ExpressionLayout * parent) override; + Expression * operand(int i) override; + int numberOfOperands() override; protected: Expression * m_arg; private: diff --git a/poincare/include/poincare/sinus.h b/poincare/include/poincare/sinus.h index 5378dd789..a970aac09 100644 --- a/poincare/include/poincare/sinus.h +++ b/poincare/include/poincare/sinus.h @@ -5,9 +5,10 @@ class Sinus : public Function { public: - Sinus(Expression * arg): Function(arg, (char*) "sin") {} + Sinus(Expression * arg, bool clone_arg=true): Function(arg, (char*) "sin", clone_arg) {} float approximate(Context& context) override; Type type() override; + Expression * clone() override; }; #endif diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index f77593878..06ffbae06 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -5,9 +5,10 @@ class Tangent : public Function { public: - Tangent(Expression * arg): Function(arg, (char*) "tan") {} + Tangent(Expression * arg, bool clone_arg=true): Function(arg, (char*) "tan", clone_arg) {} float approximate(Context& context) override; Type type() override; + Expression * clone() override; }; #endif diff --git a/poincare/src/cosinus.cpp b/poincare/src/cosinus.cpp index c21d00aa1..070b82a2a 100644 --- a/poincare/src/cosinus.cpp +++ b/poincare/src/cosinus.cpp @@ -1,6 +1,10 @@ #include #include "layout/horizontal_layout.h" +Expression * Cosinus::clone() { + return new Cosinus(m_arg, true); +} + Expression::Type Cosinus::type() { return Expression::Type::Cosinus; } diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index e7e230d11..e0ac86286 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -1,6 +1,19 @@ +extern "C" { +#include +} #include #include "layout/function_layout.h" +Function::Function(Expression * arg, char* function_name, bool clone_operands) { + m_arg = (Expression *)malloc(sizeof(Expression)); + m_function_name = function_name; + if (clone_operands) { + m_arg = arg->clone(); + } else { + m_arg = arg; + } +} + Function::~Function() { delete m_arg; } @@ -8,3 +21,15 @@ Function::~Function() { ExpressionLayout * Function::createLayout(ExpressionLayout * parent) { return new FunctionLayout(parent, m_function_name, m_arg); } + +Expression * Function::operand(int i) { + if (i==0) { + return m_arg; + } else { + return nullptr; + } +} + +int Function::numberOfOperands() { + return 1; +} diff --git a/poincare/src/sinus.cpp b/poincare/src/sinus.cpp index 6e831cb2e..9a73559a3 100644 --- a/poincare/src/sinus.cpp +++ b/poincare/src/sinus.cpp @@ -1,6 +1,10 @@ #include #include "layout/horizontal_layout.h" +Expression * Sinus::clone() { + return new Sinus(m_arg, true); +} + Expression::Type Sinus::type() { return Expression::Type::Sinus; } diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 71e9d3191..6eb92af4c 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -1,6 +1,10 @@ #include #include "layout/horizontal_layout.h" +Expression * Tangent::clone() { + return new Tangent(m_arg, true); +} + Expression::Type Tangent::type() { return Expression::Type::Tangent; } From 7f660ffbd5285396e5b0c5868312e1b3766bd109 Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Thu, 24 Mar 2016 18:24:16 +0100 Subject: [PATCH 6/8] Horizontal layout finished. Change-Id: Id02daf672668d0c946e3008bdfd0e3f00d165864 --- poincare/src/addition.cpp | 3 +- poincare/src/commutative_operation.cpp | 1 + poincare/src/expression_lexer.l | 2 +- poincare/src/layout/horizontal_layout.cpp | 39 ++++++++++++----------- poincare/src/layout/horizontal_layout.h | 5 ++- poincare/src/product.cpp | 3 +- poincare/src/subtraction.cpp | 2 +- 7 files changed, 27 insertions(+), 28 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index cb4080b33..15795ee7b 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -14,6 +14,5 @@ float Addition::operateApproximatevelyOn(float a, float b) { } ExpressionLayout * Addition::createLayout(ExpressionLayout * parent) { - //FIXME: There can be more than two operands now! :-) - return new HorizontalLayout(parent, operand(0), '+', operand(1)); + return new HorizontalLayout(parent, m_operands, m_numberOfOperands, '+'); } diff --git a/poincare/src/commutative_operation.cpp b/poincare/src/commutative_operation.cpp index 929908076..37252e0a0 100644 --- a/poincare/src/commutative_operation.cpp +++ b/poincare/src/commutative_operation.cpp @@ -30,6 +30,7 @@ int CommutativeOperation::numberOfOperands() { } Expression * CommutativeOperation::operand(int i) { + assert(i < m_numberOfOperands); return m_operands[i]; } diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index 008e5fca5..4a92ec02c 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -42,10 +42,10 @@ class Expression; %% [0-9]+ { yylval->string = yytext; return(INTEGER); } -[A-Za-z]+ { yylval->string = yytext; return(SYMBOL); } sin {return(SINUS);} cos {return(COSINUS);} tan {return(TANGENT);} +[A-Za-z]+ { yylval->string = yytext; return(SYMBOL); } \+ { return(PLUS); } \- { return(MINUS); } \* { return(MULTIPLY); } diff --git a/poincare/src/layout/horizontal_layout.cpp b/poincare/src/layout/horizontal_layout.cpp index 0ba763f4b..eebc343b0 100644 --- a/poincare/src/layout/horizontal_layout.cpp +++ b/poincare/src/layout/horizontal_layout.cpp @@ -1,29 +1,28 @@ extern "C" { -#include #include +#include +#include } #include "horizontal_layout.h" #include "string_layout.h" -HorizontalLayout::HorizontalLayout(ExpressionLayout * parent, int number_of_operands, Expression ** operands, char symbol) { - m_number_of_operands = number_of_operands; - // FIXME: This implementation is not optimal as the operator layout is created and stored a lot of times. - // The reason for this is how the layouts are drawn. - m_children_layouts = (ExpressionLayout **)malloc((2*m_number_of_operands-)*sizeof(ExpressionLayout *)); - m_operator_layout = new StringLayout(this, string, 1); +HorizontalLayout::HorizontalLayout(ExpressionLayout * parent, Expression ** operands,int number_of_operands, char symbol) : ExpressionLayout(parent) { + assert(number_of_operands > 0); + m_number_of_children = 2*number_of_operands-1; + m_children_layouts = (ExpressionLayout **)malloc(m_number_of_children*sizeof(ExpressionLayout *)); char string[2] = {symbol, '\0'}; - for (int i=1; icreateLayout(); + m_children_layouts[0] = operands[0]->createLayout(this); + for (int i=1; icreateLayout(this); } } HorizontalLayout::~HorizontalLayout() { - for (int i(0); i= 2*m_number_of_operands) { + assert(index <= m_number_of_children); + if (index < m_number_of_children) { + return m_children_layouts[index]; + } else { return nullptr; } - return m_children_layouts[index]; } KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) { KDPoint position = (KDPoint){.x = 0, .y = 0}; uint16_t index = 0; - for (int i=0;i<3;i++) { - if (m_children[i] == child) { + for (int i=0;i 0) { - ExpressionLayout * previousChild = m_children[index-1]; + ExpressionLayout * previousChild = m_children_layouts[index-1]; assert(previousChild != nullptr); position.x = previousChild->origin().x + previousChild->size().width; } diff --git a/poincare/src/layout/horizontal_layout.h b/poincare/src/layout/horizontal_layout.h index 4482aca87..0ee133f5c 100644 --- a/poincare/src/layout/horizontal_layout.h +++ b/poincare/src/layout/horizontal_layout.h @@ -6,7 +6,7 @@ class HorizontalLayout : public ExpressionLayout { public: - HorizontalLayout(ExpressionLayout * parent, int number_of_operands, Expression ** operands, char symbol); + HorizontalLayout(ExpressionLayout * parent, Expression ** operands, int number_of_children, char symbol); ~HorizontalLayout(); protected: void render(KDPoint point) override; @@ -14,9 +14,8 @@ class HorizontalLayout : public ExpressionLayout { ExpressionLayout * child(uint16_t index) override; KDPoint positionOfChild(ExpressionLayout * child) override; private: - int m_number_of_operands; + int m_number_of_children; ExpressionLayout ** m_children_layouts; - ExpressionLayout * m_operator_layout; }; #endif diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index fc888bfd8..36c93dcba 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -17,6 +17,5 @@ Expression::Type Product::type() { } ExpressionLayout * Product::createLayout(ExpressionLayout * parent) { - //FIXME: There can be more than two factors now! :-) - return new HorizontalLayout(parent, operand(0), '*', operand(1)); + return new HorizontalLayout(parent, m_operands, m_numberOfOperands, '*'); } diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 7f82f02db..448553f2a 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -14,5 +14,5 @@ Expression::Type Subtraction::type() { } ExpressionLayout * Subtraction::createLayout(ExpressionLayout * parent) { - return new HorizontalLayout(parent, m_operands[0], '-', m_operands[1]); + return new HorizontalLayout(parent, m_operands, 2, '-'); } From 46ffb55ec371146a17eecfb80ba9a296c65c496f Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Thu, 24 Mar 2016 18:30:44 +0100 Subject: [PATCH 7/8] Add parsing test for trigo functions. Change-Id: Ibcf1dd1759cd106521023f0c2adadc1f993f3eaa --- poincare/Makefile | 1 + poincare/test/trigo.cpp | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 poincare/test/trigo.cpp diff --git a/poincare/Makefile b/poincare/Makefile index de32ca59a..20a344f06 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -39,6 +39,7 @@ tests += $(addprefix poincare/test/,\ product.cpp\ simplify.cpp\ simplify_addition_integer.cpp\ + trigo.cpp\ subtraction.cpp\ ) diff --git a/poincare/test/trigo.cpp b/poincare/test/trigo.cpp new file mode 100644 index 000000000..5878efbe1 --- /dev/null +++ b/poincare/test/trigo.cpp @@ -0,0 +1,21 @@ +#include +#include +#include + +QUIZ_CASE(poincare_parse_trigo) { + { + Expression * e = Expression::parse("sin(0)"); + Expression * e2 = e->simplify(); + assert(e2->type() == Expression::Type::Sinus); + } + { + Expression * e = Expression::parse("cos(0)"); + Expression * e2 = e->simplify(); + assert(e2->type() == Expression::Type::Cosinus); + } + { + Expression * e = Expression::parse("tan(0)"); + Expression * e2 = e->simplify(); + assert(e2->type() == Expression::Type::Tangent); + } +} From 144ec9d5563243eac60a4a3a9b78e606cba8b65e Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Thu, 24 Mar 2016 18:40:41 +0100 Subject: [PATCH 8/8] Use proper english name for sine. Change-Id: I44c1bed203b126e0bd36be1efe00b7f5df9cff06 --- poincare/Makefile | 4 ++-- poincare/include/poincare.h | 4 ++-- poincare/include/poincare/cosine.h | 14 ++++++++++++++ poincare/include/poincare/cosinus.h | 14 -------------- poincare/include/poincare/expression.h | 4 ++-- poincare/include/poincare/sine.h | 14 ++++++++++++++ poincare/include/poincare/sinus.h | 14 -------------- poincare/src/cosine.cpp | 15 +++++++++++++++ poincare/src/cosinus.cpp | 15 --------------- poincare/src/expression_lexer.l | 4 ++-- poincare/src/expression_parser.y | 8 ++++---- poincare/src/sine.cpp | 15 +++++++++++++++ poincare/src/sinus.cpp | 15 --------------- poincare/test/trigo.cpp | 4 ++-- 14 files changed, 72 insertions(+), 72 deletions(-) create mode 100644 poincare/include/poincare/cosine.h delete mode 100644 poincare/include/poincare/cosinus.h create mode 100644 poincare/include/poincare/sine.h delete mode 100644 poincare/include/poincare/sinus.h create mode 100644 poincare/src/cosine.cpp delete mode 100644 poincare/src/cosinus.cpp create mode 100644 poincare/src/sine.cpp delete mode 100644 poincare/src/sinus.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 20a344f06..c7c104387 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -4,7 +4,7 @@ objs += $(addprefix poincare/src/,\ binary_operation.o\ commutative_operation.o\ context.o\ - cosinus.o\ + cosine.o\ expression.o\ expression_lexer.o\ expression_parser.o\ @@ -15,7 +15,7 @@ objs += $(addprefix poincare/src/,\ leaf_expression.o\ power.o\ product.o\ - sinus.o\ + sine.o\ subtraction.o\ symbol.o\ tangent.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 4b89926c0..21b774e7c 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h new file mode 100644 index 000000000..31f376375 --- /dev/null +++ b/poincare/include/poincare/cosine.h @@ -0,0 +1,14 @@ +#ifndef POINCARE_COSINE_H +#define POINCARE_COSINE_H + +#include + +class Cosine : public Function { + public: + Cosine(Expression * arg, bool clone_arg=true): Function(arg, (char*) "cos", clone_arg) {} + float approximate(Context& context) override; + Type type() override; + Expression * clone() override; +}; + +#endif diff --git a/poincare/include/poincare/cosinus.h b/poincare/include/poincare/cosinus.h deleted file mode 100644 index f23e66e4c..000000000 --- a/poincare/include/poincare/cosinus.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef POINCARE_COSINUS_H -#define POINCARE_COSINUS_H - -#include - -class Cosinus : public Function { - public: - Cosinus(Expression * arg, bool clone_arg=true): Function(arg, (char*) "cos", clone_arg) {} - float approximate(Context& context) override; - Type type() override; - Expression * clone() override; -}; - -#endif diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index af5e199f5..a2d4946f4 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -10,13 +10,13 @@ class Expression { public: enum class Type : uint8_t { Addition, - Cosinus, + Cosine, Float, Fraction, Integer, Power, Product, - Sinus, + Sine, Subtraction, Symbol, Tangent, diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h new file mode 100644 index 000000000..fe53563a0 --- /dev/null +++ b/poincare/include/poincare/sine.h @@ -0,0 +1,14 @@ +#ifndef POINCARE_SINE_H +#define POINCARE_SINE_H + +#include + +class Sine : public Function { + public: + Sine(Expression * arg, bool clone_arg=true): Function(arg, (char*) "sin", clone_arg) {} + float approximate(Context& context) override; + Type type() override; + Expression * clone() override; +}; + +#endif diff --git a/poincare/include/poincare/sinus.h b/poincare/include/poincare/sinus.h deleted file mode 100644 index a970aac09..000000000 --- a/poincare/include/poincare/sinus.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef POINCARE_SINUS_H -#define POINCARE_SINUS_H - -#include - -class Sinus : public Function { - public: - Sinus(Expression * arg, bool clone_arg=true): Function(arg, (char*) "sin", clone_arg) {} - float approximate(Context& context) override; - Type type() override; - Expression * clone() override; -}; - -#endif diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp new file mode 100644 index 000000000..8fafad923 --- /dev/null +++ b/poincare/src/cosine.cpp @@ -0,0 +1,15 @@ +#include +#include "layout/horizontal_layout.h" + +Expression * Cosine::clone() { + return new Cosine(m_arg, true); +} + +Expression::Type Cosine::type() { + return Expression::Type::Cosine; +} + +float Cosine::approximate(Context& context) { + // FIXME: use cosine obviously. + return m_arg->approximate(context); +} diff --git a/poincare/src/cosinus.cpp b/poincare/src/cosinus.cpp deleted file mode 100644 index 070b82a2a..000000000 --- a/poincare/src/cosinus.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include "layout/horizontal_layout.h" - -Expression * Cosinus::clone() { - return new Cosinus(m_arg, true); -} - -Expression::Type Cosinus::type() { - return Expression::Type::Cosinus; -} - -float Cosinus::approximate(Context& context) { - // FIXME: use cosinus obviously. - return m_arg->approximate(context); -} diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index 4a92ec02c..26a2dffdc 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -42,8 +42,8 @@ class Expression; %% [0-9]+ { yylval->string = yytext; return(INTEGER); } -sin {return(SINUS);} -cos {return(COSINUS);} +sin {return(SINE);} +cos {return(COSINE);} tan {return(TANGENT);} [A-Za-z]+ { yylval->string = yytext; return(SYMBOL); } \+ { return(PLUS); } diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index bb3dd2b14..43c501e64 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -54,8 +54,8 @@ void poincare_expression_yyerror(void * scanner, Expression ** expressionOutput, %token MULTIPLY %token DIVIDE %token POW -%token SINUS -%token COSINUS +%token SINE +%token COSINE %token TANGENT %token LEFT_PARENTHESIS %token RIGHT_PARENTHESIS @@ -88,8 +88,8 @@ exp: | exp DIVIDE exp { Expression * terms[2] = {$1,$3}; $$ = new Fraction(terms, false); } | exp POW exp { Expression * terms[2] = {$1,$3}; $$ = new Power(terms, false); } | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = $2; } - | SINUS LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Sinus($3); } - | COSINUS LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Cosinus($3); } + | SINE LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Sine($3); } + | COSINE LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Cosine($3); } | TANGENT LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Tangent($3); } ; diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp new file mode 100644 index 000000000..fb3d7003c --- /dev/null +++ b/poincare/src/sine.cpp @@ -0,0 +1,15 @@ +#include +#include "layout/horizontal_layout.h" + +Expression * Sine::clone() { + return new Sine(m_arg, true); +} + +Expression::Type Sine::type() { + return Expression::Type::Sine; +} + +float Sine::approximate(Context& context) { + // FIXME: use sine obviously. + return m_arg->approximate(context); +} diff --git a/poincare/src/sinus.cpp b/poincare/src/sinus.cpp deleted file mode 100644 index 9a73559a3..000000000 --- a/poincare/src/sinus.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include "layout/horizontal_layout.h" - -Expression * Sinus::clone() { - return new Sinus(m_arg, true); -} - -Expression::Type Sinus::type() { - return Expression::Type::Sinus; -} - -float Sinus::approximate(Context& context) { - // FIXME: use sinus obviously. - return m_arg->approximate(context); -} diff --git a/poincare/test/trigo.cpp b/poincare/test/trigo.cpp index 5878efbe1..700ac5b64 100644 --- a/poincare/test/trigo.cpp +++ b/poincare/test/trigo.cpp @@ -6,12 +6,12 @@ QUIZ_CASE(poincare_parse_trigo) { { Expression * e = Expression::parse("sin(0)"); Expression * e2 = e->simplify(); - assert(e2->type() == Expression::Type::Sinus); + assert(e2->type() == Expression::Type::Sine); } { Expression * e = Expression::parse("cos(0)"); Expression * e2 = e->simplify(); - assert(e2->type() == Expression::Type::Cosinus); + assert(e2->type() == Expression::Type::Cosine); } { Expression * e = Expression::parse("tan(0)");