mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
Merge changes I6b4d6be5,Ie87dc145,I87e12b9c,I5d37ed0a,Ia52f38da
* changes: Update functions to use the clone interface. Horizontal layout Remove call to get_char to fix tests. Rename text_input to utils, add a util in it. Add the Function and trig functions classes and layout.
This commit is contained in:
@@ -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)
|
||||
|
||||
12
app/app.cpp
12
app/app.cpp
@@ -6,7 +6,7 @@ extern "C" {
|
||||
|
||||
#include <poincare.h>
|
||||
|
||||
#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();
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -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/,\
|
||||
|
||||
@@ -3,13 +3,17 @@
|
||||
|
||||
#include <poincare/addition.h>
|
||||
#include <poincare/context.h>
|
||||
#include <poincare/cosinus.h>
|
||||
#include <poincare/expression.h>
|
||||
#include <poincare/fraction.h>
|
||||
#include <poincare/float.h>
|
||||
#include <poincare/fraction.h>
|
||||
#include <poincare/function.h>
|
||||
#include <poincare/integer.h>
|
||||
#include <poincare/power.h>
|
||||
#include <poincare/product.h>
|
||||
#include <poincare/sinus.h>
|
||||
#include <poincare/subtraction.h>
|
||||
#include <poincare/symbol.h>
|
||||
#include <poincare/tangent.h>
|
||||
|
||||
#endif
|
||||
|
||||
14
poincare/include/poincare/cosinus.h
Normal file
14
poincare/include/poincare/cosinus.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef POINCARE_COSINUS_H
|
||||
#define POINCARE_COSINUS_H
|
||||
|
||||
#include <poincare/function.h>
|
||||
|
||||
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
|
||||
@@ -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();
|
||||
|
||||
19
poincare/include/poincare/function.h
Normal file
19
poincare/include/poincare/function.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef POINCARE_FUNCTION_H
|
||||
#define POINCARE_FUNCTION_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
|
||||
class Function : public Expression {
|
||||
public:
|
||||
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:
|
||||
char* m_function_name;
|
||||
};
|
||||
|
||||
#endif
|
||||
14
poincare/include/poincare/sinus.h
Normal file
14
poincare/include/poincare/sinus.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef POINCARE_SINUS_H
|
||||
#define POINCARE_SINUS_H
|
||||
|
||||
#include <poincare/function.h>
|
||||
|
||||
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
|
||||
14
poincare/include/poincare/tangent.h
Normal file
14
poincare/include/poincare/tangent.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef POINCARE_TANGENT_H
|
||||
#define POINCARE_TANGENT_H
|
||||
|
||||
#include <poincare/function.h>
|
||||
|
||||
class Tangent : public Function {
|
||||
public:
|
||||
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
|
||||
15
poincare/src/cosinus.cpp
Normal file
15
poincare/src/cosinus.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <poincare/cosinus.h>
|
||||
#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);
|
||||
}
|
||||
@@ -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); }
|
||||
|
||||
@@ -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); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
35
poincare/src/function.cpp
Normal file
35
poincare/src/function.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
extern "C" {
|
||||
#include <stdlib.h>
|
||||
}
|
||||
#include <poincare/function.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
73
poincare/src/layout/function_layout.cpp
Normal file
73
poincare/src/layout/function_layout.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
extern "C" {
|
||||
#include <kandinsky.h>
|
||||
#include <assert.h>
|
||||
}
|
||||
#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;
|
||||
}
|
||||
|
||||
21
poincare/src/layout/function_layout.h
Normal file
21
poincare/src/layout/function_layout.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef POINCARE_FUNCTION_LAYOUT_H
|
||||
#define POINCARE_FUNCTION_LAYOUT_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
#include <poincare/expression_layout.h>
|
||||
|
||||
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
|
||||
|
||||
@@ -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; i<m_number_of_operands; i++) {
|
||||
m_operands[2*i-1] = m_operator_layout;
|
||||
m_operands[2*i] = operands[i]->createLayout();
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalLayout::~HorizontalLayout() {
|
||||
delete m_children[2];
|
||||
delete m_children[1];
|
||||
delete m_children[0];
|
||||
for (int i(0); i<m_numberOfOperands; i++) {
|
||||
delete m_operands[2*i];
|
||||
}
|
||||
free(m_operands);
|
||||
delete m_operator_layout;
|
||||
}
|
||||
|
||||
void HorizontalLayout::render(KDPoint point) {
|
||||
// Nothing to render "per se"
|
||||
}
|
||||
void HorizontalLayout::render(KDPoint point) { }
|
||||
|
||||
KDSize HorizontalLayout::computeSize() {
|
||||
KDSize size = (KDSize){.width = 0, .height = 0};
|
||||
@@ -39,10 +42,10 @@ KDSize HorizontalLayout::computeSize() {
|
||||
}
|
||||
|
||||
ExpressionLayout * HorizontalLayout::child(uint16_t index) {
|
||||
if (index >= 3) {
|
||||
if (index >= 2*m_number_of_operands) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_children[index];
|
||||
return m_children_layouts[index];
|
||||
}
|
||||
|
||||
KDPoint HorizontalLayout::positionOfChild(ExpressionLayout * child) {
|
||||
|
||||
@@ -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
|
||||
|
||||
15
poincare/src/sinus.cpp
Normal file
15
poincare/src/sinus.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <poincare/sinus.h>
|
||||
#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);
|
||||
}
|
||||
15
poincare/src/tangent.cpp
Normal file
15
poincare/src/tangent.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <poincare/tangent.h>
|
||||
#include "layout/horizontal_layout.h"
|
||||
|
||||
Expression * Tangent::clone() {
|
||||
return new Tangent(m_arg, true);
|
||||
}
|
||||
|
||||
Expression::Type Tangent::type() {
|
||||
return Expression::Type::Tangent;
|
||||
}
|
||||
|
||||
float Tangent::approximate(Context& context) {
|
||||
// FIXME: use tangent obviously.
|
||||
return m_arg->approximate(context);
|
||||
}
|
||||
@@ -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?
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user