mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[Poincare] Handle symbol/context
This commit is contained in:
17
app/app.cpp
17
app/app.cpp
@@ -34,14 +34,17 @@ void draw_lines_from_center() {
|
||||
}
|
||||
}
|
||||
|
||||
void plot(Expression * e, Variable * v, float xMin, float xMax, float yMin, float yMax) {
|
||||
void plot(Expression * e, float xMin, float xMax, float yMin, float yMax) {
|
||||
Context plotContext;
|
||||
KDCoordinate screenWidth = 240;
|
||||
KDCoordinate screenHeight = 160;
|
||||
KDPoint previousPoint;
|
||||
for (KDCoordinate i=0;i<screenWidth; i++) {
|
||||
float x = xMin + (xMax-xMin)/screenWidth*i;
|
||||
v->setValue(x);
|
||||
float y = e->approximate();
|
||||
Float xExp = Float(x);
|
||||
//plotContext["x"] = xExp;
|
||||
plotContext.setExpressionForSymbolName(&xExp, "x");
|
||||
float y = e->approximate(plotContext);
|
||||
KDCoordinate j = ((y-yMin)/(yMax-yMin)*screenHeight);
|
||||
KDPoint currentPoint = KDPointMake(i,screenHeight-j);
|
||||
if (i>0) {
|
||||
@@ -53,8 +56,7 @@ void plot(Expression * e, Variable * v, float xMin, float xMax, float yMin, floa
|
||||
|
||||
void funnyPlot() {
|
||||
Expression * e = Expression::parse("1/x");
|
||||
Variable * v = Variable::VariableNamed("x");
|
||||
plot(e,v, 1.0f, 4.0f, 0.0f, 1.0f);
|
||||
plot(e, 1.0f, 4.0f, 0.0f, 1.0f);
|
||||
delete e;
|
||||
}
|
||||
|
||||
@@ -91,10 +93,7 @@ void interactive_expression_parsing() {
|
||||
ExpressionLayout * l = e->createLayout(nullptr);
|
||||
if (l) {
|
||||
l->draw(KDPointMake(0,100));
|
||||
Variable * v = Variable::VariableNamed("x");
|
||||
if (v) {
|
||||
plot(e,v, 0.0f, 3.0f, 0.0f, 2.0f);
|
||||
}
|
||||
plot(e, 0.0f, 3.0f, 0.0f, 2.0f);
|
||||
delete l;
|
||||
}
|
||||
delete e;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
SFLAGS += -Ipoincare/include
|
||||
objs += $(addprefix poincare/src/, addition.o expression.o integer.o fraction.o expression_lexer.o expression_parser.o variable.o)
|
||||
objs += $(addprefix poincare/src/, addition.o context.o expression.o float.o integer.o fraction.o expression_lexer.o expression_parser.o product.o symbol.o)
|
||||
objs += $(addprefix poincare/src/layout/, expression_layout.o fraction_layout.o horizontal_layout.o string_layout.o)
|
||||
tests += $(addprefix poincare/test/, integer.cpp)
|
||||
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
#define POINCARE_H
|
||||
|
||||
#include <poincare/addition.h>
|
||||
#include <poincare/context.h>
|
||||
#include <poincare/expression.h>
|
||||
#include <poincare/fraction.h>
|
||||
#include <poincare/float.h>
|
||||
#include <poincare/integer.h>
|
||||
#include <poincare/power.h>
|
||||
#include <poincare/variable.h>
|
||||
#include <poincare/product.h>
|
||||
#include <poincare/symbol.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,7 @@ class Addition : public Expression {
|
||||
Addition(Expression * first_operand, Expression * second_operand);
|
||||
~Addition();
|
||||
ExpressionLayout * createLayout(ExpressionLayout * parent) override;
|
||||
float approximate() override;
|
||||
float approximate(Context& context) override;
|
||||
private:
|
||||
Expression * m_children[2];
|
||||
};
|
||||
|
||||
26
poincare/include/poincare/context.h
Normal file
26
poincare/include/poincare/context.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef POINCARE_CONTEXT_H
|
||||
#define POINCARE_CONTEXT_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
|
||||
//TODO: We should probably make a COPY of the expressions we store
|
||||
|
||||
class Context {
|
||||
public:
|
||||
Context();
|
||||
~Context();
|
||||
Expression * operator[](const char * symbol_name) const;
|
||||
void setExpressionForSymbolName(Expression * expression, const char * symbol_name);
|
||||
/*
|
||||
Expression const& operator[](const char * symbol_name) const;
|
||||
Expression& operator[](const char * symbol_name);
|
||||
*/
|
||||
private:
|
||||
struct ContextPair {
|
||||
const char * name;
|
||||
Expression * expression;
|
||||
};
|
||||
ContextPair * m_pairs;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <poincare/expression_layout.h>
|
||||
#include <kandinsky.h>
|
||||
|
||||
class Context;
|
||||
|
||||
class Expression {
|
||||
public:
|
||||
static Expression * parse(char * string);
|
||||
@@ -19,7 +21,7 @@ class Expression {
|
||||
//virtual bool identicalTo(Expression * e);
|
||||
//virtual Expression * simplify();
|
||||
|
||||
virtual float approximate() = 0;
|
||||
virtual float approximate(Context& context) = 0;
|
||||
/*private:
|
||||
void forEachChild(ExpressionAction);
|
||||
*/
|
||||
|
||||
17
poincare/include/poincare/float.h
Normal file
17
poincare/include/poincare/float.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef POINCARE_FLOAT_H
|
||||
#define POINCARE_FLOAT_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
|
||||
class Float : public Expression {
|
||||
public:
|
||||
Float(float f);
|
||||
~Float();
|
||||
|
||||
ExpressionLayout * createLayout(ExpressionLayout * parent) override;
|
||||
float approximate(Context& context) override;
|
||||
private:
|
||||
float m_float;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -8,7 +8,7 @@ class Fraction : public Expression {
|
||||
Fraction(Expression * numerator, Expression * denominator);
|
||||
~Fraction();
|
||||
ExpressionLayout * createLayout(ExpressionLayout * parent) override;
|
||||
float approximate() override;
|
||||
float approximate(Context& context) override;
|
||||
private:
|
||||
Expression * m_numerator;
|
||||
Expression * m_denominator;
|
||||
|
||||
@@ -31,15 +31,15 @@ class Integer : public Expression {
|
||||
virtual bool identicalTo(Expression * e);
|
||||
*/
|
||||
virtual ExpressionLayout * createLayout(ExpressionLayout * parent);
|
||||
virtual float approximate();
|
||||
virtual float approximate(Context& context);
|
||||
private:
|
||||
int8_t ucmp(const Integer &other) const; // -1, 0, or 1
|
||||
Integer usum(const Integer &other, bool subtract, bool output_negative) const;
|
||||
Integer add(const Integer &other, bool inverse_other_negative) const;
|
||||
/* WARNING: This constructor takes ownership of the bits array and will free it! */
|
||||
Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative);
|
||||
uint16_t m_numberOfDigits; // In base native_uint_max
|
||||
native_uint_t * m_digits; // LITTLE-ENDIAN
|
||||
uint16_t m_numberOfDigits; // In base native_uint_max
|
||||
bool m_negative;
|
||||
/*
|
||||
// TODO: Small-int optimization
|
||||
|
||||
16
poincare/include/poincare/product.h
Normal file
16
poincare/include/poincare/product.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef POINCARE_PRODUCT_H
|
||||
#define POINCARE_PRODUCT_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
|
||||
class Product : public Expression {
|
||||
public:
|
||||
Product(Expression * first_factor, Expression * second_factor);
|
||||
~Product();
|
||||
ExpressionLayout * createLayout(ExpressionLayout * parent) override;
|
||||
float approximate(Context& context) override;
|
||||
private:
|
||||
Expression * m_children[2];
|
||||
};
|
||||
|
||||
#endif
|
||||
16
poincare/include/poincare/symbol.h
Normal file
16
poincare/include/poincare/symbol.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef POINCARE_SYMBOL_H
|
||||
#define POINCARE_SYMBOL_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
|
||||
class Symbol : public Expression {
|
||||
public:
|
||||
Symbol(char * name);
|
||||
~Symbol();
|
||||
ExpressionLayout * createLayout(ExpressionLayout * parent) override;
|
||||
float approximate(Context& context) override;
|
||||
private:
|
||||
char * m_name;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,21 +0,0 @@
|
||||
#ifndef POINCARE_VARIABLE_H
|
||||
#define POINCARE_VARIABLE_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
|
||||
class Variable : public Expression {
|
||||
public:
|
||||
Variable(char * name);
|
||||
~Variable();
|
||||
static Variable * VariableNamed(char * name);
|
||||
ExpressionLayout * createLayout(ExpressionLayout * parent) override;
|
||||
float approximate() override;
|
||||
void setValue(float value);
|
||||
private:
|
||||
static void RegisterVariable(Variable * v);
|
||||
static void UnregisterVariable(Variable * v);
|
||||
char * m_name;
|
||||
float m_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -11,8 +11,8 @@ Addition::~Addition() {
|
||||
delete m_children[0];
|
||||
}
|
||||
|
||||
float Addition::approximate() {
|
||||
return m_children[0]->approximate() + m_children[1]->approximate();
|
||||
float Addition::approximate(Context& context) {
|
||||
return m_children[0]->approximate(context) + m_children[1]->approximate(context);
|
||||
}
|
||||
|
||||
ExpressionLayout * Addition::createLayout(ExpressionLayout * parent) {
|
||||
|
||||
45
poincare/src/context.cpp
Normal file
45
poincare/src/context.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <poincare/context.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_CONTEXT_PAIRS 10
|
||||
|
||||
Context::Context() {
|
||||
size_t size = sizeof(ContextPair)*MAX_CONTEXT_PAIRS;
|
||||
m_pairs = (ContextPair *)malloc(size);
|
||||
memset(m_pairs, 0, size);
|
||||
}
|
||||
|
||||
Context::~Context() {
|
||||
free(m_pairs);
|
||||
}
|
||||
|
||||
Expression * Context::operator[](const char * symbol_name) const {
|
||||
for (int16_t i=0; i<MAX_CONTEXT_PAIRS; i++) {
|
||||
ContextPair p = m_pairs[i];
|
||||
if (p.name != NULL && strcmp(p.name, symbol_name) == 0) {
|
||||
return p.expression;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Context::setExpressionForSymbolName(Expression * expression, const char * symbol_name) {
|
||||
for (int16_t i=0; i<MAX_CONTEXT_PAIRS; i++) {
|
||||
ContextPair * p = &m_pairs[i];
|
||||
if (p->name == NULL) {
|
||||
// FIXME: Should be copied or retained!
|
||||
// What follows is *ugly*
|
||||
p->name = symbol_name;
|
||||
p->expression = expression;
|
||||
return;
|
||||
} else if (strcmp(p->name, symbol_name) == 0) {
|
||||
// FIXME: Release, retain
|
||||
// What follows is *awful*
|
||||
p->expression = expression;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Hu-oh, no more space!
|
||||
abort();
|
||||
}
|
||||
@@ -50,6 +50,7 @@
|
||||
|
||||
[0-9]+ { yylval->string = yytext; return(INTEGER); }
|
||||
\/ { return(DIVIDE); }
|
||||
\* { return(MULTIPLY); }
|
||||
\^ { return(POW); }
|
||||
\+ { return(PLUS); }
|
||||
[A-Za-z]+ { yylval->string = yytext; return(SYMBOL); }
|
||||
|
||||
@@ -59,6 +59,7 @@ void poincare_expression_yyerror(yyscan_t scanner, Expression ** expressionOutpu
|
||||
|
||||
/* The DIVIDE and POW tokens use no value */
|
||||
%token DIVIDE
|
||||
%token MULTIPLY
|
||||
%token POW
|
||||
%token PLUS
|
||||
|
||||
@@ -92,10 +93,11 @@ Root:
|
||||
}
|
||||
|
||||
exp:
|
||||
INTEGER { $$ = new Integer($1); }
|
||||
| SYMBOL { $$ = new Variable($1); }
|
||||
| exp DIVIDE exp { $$ = new Fraction($1,$3); }
|
||||
| exp PLUS exp { $$ = new Addition($1,$3); }
|
||||
INTEGER { $$ = new Integer($1); }
|
||||
| SYMBOL { $$ = new Symbol($1); }
|
||||
| exp DIVIDE exp { $$ = new Fraction($1,$3); }
|
||||
| exp MULTIPLY exp { $$ = new Product($1,$3); }
|
||||
| exp PLUS exp { $$ = new Addition($1,$3); }
|
||||
/* | exp POW exp { $$ = new Power($1,$3); } */
|
||||
;
|
||||
|
||||
|
||||
17
poincare/src/float.cpp
Normal file
17
poincare/src/float.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <poincare/float.h>
|
||||
#include <assert.h>
|
||||
|
||||
Float::Float(float f) : m_float(f) {
|
||||
}
|
||||
|
||||
Float::~Float() {
|
||||
}
|
||||
|
||||
float Float::approximate(Context& context) {
|
||||
return m_float;
|
||||
}
|
||||
|
||||
ExpressionLayout * Float::createLayout(ExpressionLayout * parent) {
|
||||
assert(0); // Should not come here, ever...
|
||||
return nullptr;
|
||||
}
|
||||
@@ -16,7 +16,7 @@ ExpressionLayout * Fraction::createLayout(ExpressionLayout * parent) {
|
||||
return new FractionLayout(parent, m_numerator, m_denominator);
|
||||
}
|
||||
|
||||
float Fraction::approximate() {
|
||||
float Fraction::approximate(Context& context) {
|
||||
// TODO: handle division by zero
|
||||
return m_numerator->approximate()/m_denominator->approximate();
|
||||
return m_numerator->approximate(context)/m_denominator->approximate(context);
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ Integer Integer::operator/(const Integer &other) const {
|
||||
return Division(*this, other).m_quotient;
|
||||
}
|
||||
|
||||
float Integer::approximate() {
|
||||
float Integer::approximate(Context& context) {
|
||||
union {
|
||||
uint32_t uint_result;
|
||||
float float_result;
|
||||
|
||||
20
poincare/src/product.cpp
Normal file
20
poincare/src/product.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <poincare/product.h>
|
||||
#include "layout/horizontal_layout.h"
|
||||
|
||||
Product::Product(Expression * first_factor, Expression * second_factor) {
|
||||
m_children[0] = first_factor;
|
||||
m_children[1] = second_factor;
|
||||
}
|
||||
|
||||
Product::~Product() {
|
||||
delete m_children[1];
|
||||
delete m_children[0];
|
||||
}
|
||||
|
||||
float Product::approximate(Context& context) {
|
||||
return m_children[0]->approximate(context) * m_children[1]->approximate(context);
|
||||
}
|
||||
|
||||
ExpressionLayout * Product::createLayout(ExpressionLayout * parent) {
|
||||
return new HorizontalLayout(parent, m_children[0], '*', m_children[1]);
|
||||
}
|
||||
24
poincare/src/symbol.cpp
Normal file
24
poincare/src/symbol.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <poincare/symbol.h>
|
||||
#include <poincare/context.h>
|
||||
#include <stdlib.h>
|
||||
#include "layout/string_layout.h"
|
||||
|
||||
Symbol::Symbol(char * name) {
|
||||
size_t length = strlen(name);
|
||||
m_name = (char *)malloc(sizeof(char)*length+1);
|
||||
memcpy(m_name, name, length);
|
||||
m_name[length] = 0;
|
||||
}
|
||||
|
||||
Symbol::~Symbol() {
|
||||
free(m_name);
|
||||
}
|
||||
|
||||
float Symbol::approximate(Context& context) {
|
||||
return context[m_name]->approximate(context);
|
||||
}
|
||||
|
||||
ExpressionLayout * Symbol::createLayout(ExpressionLayout * parent) {
|
||||
size_t length = strlen(m_name);
|
||||
return new StringLayout(parent, m_name, length);
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
#include <poincare/variable.h>
|
||||
#include <stdlib.h>
|
||||
#include "layout/string_layout.h"
|
||||
|
||||
Variable ** sRegisteredVariables = NULL;
|
||||
int16_t sRegisteredVariableCount = 0;
|
||||
#define MAX_REGISTERED_VARIABLES 10
|
||||
|
||||
Variable::Variable(char * name) :
|
||||
m_value(0.0f) {
|
||||
size_t length = strlen(name);
|
||||
m_name = (char *)malloc(sizeof(char)*length+1);
|
||||
memcpy(m_name, name, length);
|
||||
m_name[length] = 0;
|
||||
RegisterVariable(this);
|
||||
}
|
||||
|
||||
Variable::~Variable() {
|
||||
UnregisterVariable(this);
|
||||
free(m_name);
|
||||
}
|
||||
|
||||
float Variable::approximate() {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
ExpressionLayout * Variable::createLayout(ExpressionLayout * parent) {
|
||||
size_t length = strlen(m_name);
|
||||
return new StringLayout(parent, m_name, length);
|
||||
}
|
||||
|
||||
Variable * Variable::VariableNamed(char * name) {
|
||||
for (int16_t i=0; i<sRegisteredVariableCount; i++) {
|
||||
Variable * currentVariable = sRegisteredVariables[i];
|
||||
if (strcmp(currentVariable->m_name, name) == 0) {
|
||||
return currentVariable;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Variable::setValue(float value) {
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
void Variable::RegisterVariable(Variable * v) {
|
||||
if (sRegisteredVariables == NULL) {
|
||||
sRegisteredVariables = (Variable **)malloc(MAX_REGISTERED_VARIABLES*sizeof(Variable *));
|
||||
}
|
||||
sRegisteredVariables[sRegisteredVariableCount++] = v;
|
||||
}
|
||||
|
||||
void Variable::UnregisterVariable(Variable * v) {
|
||||
// TODO!
|
||||
}
|
||||
Reference in New Issue
Block a user