[poincare] Get Opposite class to build

This commit is contained in:
Romain Goyet
2018-08-08 18:11:27 +02:00
parent 5f620b0588
commit 413ff834b9
11 changed files with 136 additions and 72 deletions

View File

@@ -4,7 +4,8 @@
#include <poincare/expression_node.h>
#include <poincare/expression.h>
#include <poincare/complex.h>
#include <poincare/allocation_failed_layout_node.h>
#include <poincare/allocation_failure_layout_node.h>
#include <poincare/char_layout_node.h>
#include <stdio.h>
namespace Poincare {
@@ -14,6 +15,7 @@ class AllocationFailureExpressionNode : public T {
public:
AllocationFailureExpressionNode() : T() {}
AllocationFailureExpressionNode(T node) : T(node) {}
// ExpressionNode
ExpressionNode::Sign sign() const override { return ExpressionNode::Sign::Unknown; }
ExpressionNode::Type type() const override { return ExpressionNode::Type::AllocationFailure; }
@@ -25,7 +27,8 @@ public:
}
return PrintFloat::convertFloatToText<float>(NAN, buffer, bufferSize, numberOfSignificantDigits, floatDisplayMode);
}
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { return AllocationFailedLayoutRef(); }
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { return LayoutRef(CharLayoutNode::FailedAllocationStaticNode()); }
// FIXME: Use EmptyLayoutNode here above, once EmptyLayout has been cleaned up
// TreeNode
size_t size() const override { return sizeof(AllocationFailureExpressionNode<T>); }

View File

@@ -1,30 +1,30 @@
#ifndef POINCARE_ALLOCATION_FAILED_LAYOUT_NODE_H
#define POINCARE_ALLOCATION_FAILED_LAYOUT_NODE_H
#ifndef POINCARE_ALLOCATION_FAILURE_LAYOUT_NODE_H
#define POINCARE_ALLOCATION_FAILURE_LAYOUT_NODE_H
#include "allocation_failure_node.h"
#include "layout_node.h"
#include "layout_reference.h"
#include "layout_cursor.h"
namespace Poincare {
class AllocationFailedLayoutNode : public LayoutNode {
template <typename T>
class AllocationFailureLayoutNode : public AllocationFailureNode<T> {
public:
static AllocationFailedLayoutNode * FailedAllocationStaticNode() {
return static_cast<AllocationFailedLayoutNode *>(LayoutNode::FailedAllocationStaticNode());
}
// TreeNode
bool isAllocationFailure() const override { return true; }
size_t size() const override { return sizeof(AllocationFailedLayoutNode); }
size_t size() const override { return sizeof(AllocationFailureLayoutNode<T>); }
#if TREE_LOG
const char * description() const override { return "AllocationFailedLayout"; }
const char * description() const override { return "AllocationFailureLayout"; }
#endif
int numberOfChildren() const override { return 0; }
// LayoutNode
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
assert(false);
return 0;
/*
int descriptionLength = strlen(description()) + 1;
return strlcpy(buffer, description(), bufferSize < descriptionLength ? bufferSize : descriptionLength);
*/
}
void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override {}
void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override {}
@@ -48,10 +48,13 @@ private:
void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {}
};
class AllocationFailedLayoutRef : public LayoutReference {
/*
template <typename T>
class AllocationFailureLayoutRef : public LayoutReference {
public:
AllocationFailedLayoutRef() : LayoutReference(TreePool::sharedPool()->createTreeNode<AllocationFailedLayoutNode>()) {}
AllocationFailedLayoutRef() : LayoutReference(TreePool::sharedPool()->createTreeNode<AllocationFailureLayoutNode<T>>()) {}
};
*/
}

View File

@@ -0,0 +1,23 @@
#ifndef POINCARE_ALLOCATION_FAILURE_NODE_H
#define POINCARE_ALLOCATION_FAILURE_NODE_H
namespace Poincare {
template <typename T>
class AllocationFailureNode : public T {
public:
AllocationFailureNode() : T() {}
AllocationFailureNode(T node) : T(node) {}
// TreeNode
size_t size() const override { return sizeof(AllocationFailureNode<T>); }
#if TREE_LOG
const char * description() const override { return "AllocationFailure"; }
#endif
int numberOfChildren() const override { return 0; }
bool isAllocationFailure() const override { return true; }
};
}
#endif

View File

@@ -27,6 +27,7 @@ public:
bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override;
// TreeNode
static CharLayoutNode * FailedAllocationStaticNode();
size_t size() const override { return sizeof(CharLayoutNode); }
int numberOfChildren() const override { return 0; }
#if TREE_LOG

View File

@@ -11,9 +11,8 @@ class Division;
class DivisionNode : public ExpressionNode {
public:
static DivisionNode * FailedAllocationStaticNode();
// TreeNode
static DivisionNode * FailedAllocationStaticNode();
size_t size() const override { return sizeof(DivisionNode); }
#if TREE_LOG
const char * description() const override { return "Division"; }
@@ -59,7 +58,10 @@ private:
class Division : public Expression {
public:
Division(Expression numerator, Expression denominator);
Division(Expression numerator, Expression denominator) {
addChild(numberator);
addChild(denominator);
}
Division(const DivisionNode * n) : Expression(n) {}
Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit);
};

View File

@@ -73,7 +73,7 @@ private:
class EmptyLayoutRef : public LayoutReference {
public:
EmptyLayoutRef(EmptyLayoutNode::Color color = EmptyLayoutNode::Color::Yellow, bool visible = true, KDText::FontSize fontSize = KDText::FontSize::Large, bool margins = true) :
LayoutReference(TreePool::sharedPool()->createTreeNode<EmptyLayoutNode>(), true)
LayoutReference(TreePool::sharedPool()->createTreeNode<EmptyLayoutNode>())
{
if (!(node()->isAllocationFailure())) {
typedNode()->setColor(color);

View File

@@ -10,11 +10,10 @@ class Opposite;
class OppositeNode : public ExpressionNode {
public:
static OppositeNode * FailedAllocationStaticNode();
template<typename T> static Complex<T> compute(const std::complex<T> c, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree) { return Complex<T>(-c); }
// TreeNode
static OppositeNode * FailedAllocationStaticNode();
size_t size() const override { return sizeof(OppositeNode); }
#if TREE_LOG
const char * description() const override { return "Opposite"; }
@@ -45,13 +44,10 @@ public:
class Opposite : public Expression {
public:
Opposite(Expression operand);
Opposite(const OppositeNode * n) : Expression(n) {}
/* : Expression(TreePool::sharedPool()->createTreeNode<OppositeNode>()) {
Opposite(Expression operand) : Expression(TreePool::sharedPool()->createTreeNode<OppositeNode>()) {
replaceChildAtIndexInPlace(0, operand);
}
*/
Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit);
};

View File

@@ -9,18 +9,23 @@
namespace Poincare {
class Power : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
friend class Multiplication;
friend class NthRoot;
friend class SquareRoot;
friend class Addition;
friend class Division;
friend class Round;
friend class Symbol;
class Power;
class PowerNode : public ExpressionNode {
public:
Type type() const override;
Sign sign() const override;
// TreeNode
static PowerNode * FailedAllocationStaticNode();
size_t size() const override { return sizeof(PowerNode); }
#if TREE_LOG
const char * description() const override { return "Division"; }
#endif
int numberOfChildren() const override { return 2; }
// Properties
virtual Type type() const override { return Type::Power; }
virtual Sign sign() const override;
virtual Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override;
int polynomialDegree(char symbolName) const override;
int privateGetPolynomialCoefficients(char symbolName, Expression * coefficients[]) const override;
template<typename T> static std::complex<T> compute(const std::complex<T> c, const std::complex<T> d);
@@ -28,7 +33,6 @@ private:
constexpr static int k_maxNumberOfTermsInExpandedMultinome = 25;
constexpr static int k_maxExactPowerMatrix = 100;
/* Property */
Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) override;
/* Layout */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
bool needsParenthesesWithParent(SerializableNode * parentNode) const override;
@@ -67,6 +71,17 @@ private:
}
};
class Power : public Expression {
public:
Power(Expression base, Expression exponent);
Power(const PowerNode * n) : Expression(n) {}
Expression setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit);
Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit);
};
}
#endif

View File

@@ -4,6 +4,11 @@
namespace Poincare {
CharLayoutNode * CharLayoutNode::FailedAllocationStaticNode() {
static AllocationFailureLayoutNode<CharLayoutNode> failure;
return &failure;
}
// LayoutNode
void CharLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) {
if (cursor->position() == LayoutCursor::Position::Right) {

View File

@@ -3,7 +3,7 @@
/* When calling the parser, we will provide yyparse with an extra parameter : a
* backpointer to the resulting expression. */
%parse-param { Poincare::Expression ** expressionOutput }
%parse-param { Poincare::Expression * expressionOutput }
%{
#include <poincare.h>
@@ -14,7 +14,7 @@
/* Declare our error-handling function. Since we're making a re-entrant parser,
* it takes a context parameter as its first input. */
void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char const *msg);
void poincare_expression_yyerror(Poincare::Expression * expressionOutput, char const *msg);
/* Bison expects to use __builtin_memcpy. We don't want to provide this, but
* instead we do provide regular memcpy. Let's instruct Bison to use it. */
@@ -28,11 +28,14 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char
* when parsing (a/b) we want to create a new Division), or a string (this will
* be useful to retrieve the value of Integers for example). */
%union {
Poincare::Expression * expression;
Poincare::Symbol * symbol;
Poincare::Expression expression;
Poincare::Symbol symbol;
/*
Poincare::ListData * listData;
Poincare::MatrixData * matrixData;
Poincare::StaticHierarchy<0> * function;
*/
/* Caution: all the const char * are NOT guaranteed to be NULL-terminated!
* While Flex guarantees that yytext is NULL-terminated when building tokens,
* it does so by temporarily swapping in a NULL terminated in the input text.
@@ -130,16 +133,22 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char
/* MATRICES_ARE_DEFINED */
%type <matrixData> mtxData;
/* FIXME: no destructors, Expressions are GCed */
/* During error recovery, some symbols need to be discarded. We need to tell
* Bison how to get rid of them. Depending on the type of the symbol, it may
* have some heap-allocated data that need to be discarded. */
/*
%destructor { delete $$; } FUNCTION
%destructor { delete $$; } UNDEFINED final_exp exp pow factor bang term number EMPTY
%destructor { delete $$; } lstData
*/
/* MATRICES_ARE_DEFINED */
/*
%destructor { delete $$; } mtxData
%destructor { delete $$; } symb
*/
%%
@@ -149,14 +158,18 @@ Root:
}
;
/*
lstData: exp { $$ = new Poincare::ListData($1); }
| lstData COMMA exp { $$ = $1; $$->pushExpression($3); }
;
*/
/* MATRICES_ARE_DEFINED */
/*
mtxData: LEFT_BRACKET lstData RIGHT_BRACKET { $$ = new Poincare::MatrixData($2, false); $2->detachOperands(); delete $2; }
| mtxData LEFT_BRACKET lstData RIGHT_BRACKET { if ($3->numberOfChildren() != $1->numberOfColumns()) { delete $1; delete $3; YYERROR; } ; $$ = $1; $$->pushListData($3, false); $3->detachOperands(); delete $3; }
;
*/
/* When approximating expressions to double, results are bounded by 1E308 (and
* 1E-308 for small numbers). We thus accept decimals whose exponents are in
@@ -167,24 +180,28 @@ mtxData: LEFT_BRACKET lstData RIGHT_BRACKET { $$ = new Poincare::MatrixData($2,
* of the exponent digits is above 4 (0.00...-256 times-...01E1256=1E1000 is
* accepted and 1000-...256times...-0E10000 = 1E10256, 10256 does not overflow
* an int32_t). */
number : DIGITS { $$ = new Poincare::Rational(Poincare::Integer($1.address, false)); }
| DOT DIGITS { $$ = new Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, nullptr, 0, false)); }
| DIGITS DOT DIGITS { $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), Poincare::Decimal::exponent($1.address, $1.length, $3.address, $3.length, nullptr, 0, false)); }
| DOT DIGITS EE DIGITS { if ($4.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, $4.address, $4.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), exponent); }
| DIGITS DOT DIGITS EE DIGITS { if ($5.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent($1.address, $1.length, $3.address, $3.length, $5.address, $5.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), exponent); }
| DIGITS EE DIGITS { if ($3.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent($1.address, $1.length, nullptr, 0, $3.address, $3.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, nullptr, 0, false), exponent); }
| DOT DIGITS EE MINUS DIGITS { if ($5.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, $5.address, $5.length, true); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), exponent); }
number : DIGITS { $$ = Poincare::Rational(Poincare::Integer($1.address, false)); }
/*
| DOT DIGITS { $$ = Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, nullptr, 0, false)); }
| DIGITS DOT DIGITS { $$ = Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), Poincare::Decimal::exponent($1.address, $1.length, $3.address, $3.length, nullptr, 0, false)); }
| DOT DIGITS EE DIGITS { if ($4.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, $4.address, $4.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), exponent); }
| DIGITS DOT DIGITS EE DIGITS { if ($5.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent($1.address, $1.length, $3.address, $3.length, $5.address, $5.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), exponent); }
| DIGITS EE DIGITS { if ($3.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent($1.address, $1.length, nullptr, 0, $3.address, $3.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, nullptr, 0, false), exponent); }
| DOT DIGITS EE MINUS DIGITS { if ($5.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, $5.address, $5.length, true); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), exponent); }
| DIGITS DOT DIGITS EE MINUS DIGITS { if ($6.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent($1.address, $1.length, $3.address, $3.length, $6.address, $6.length, true); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), exponent); }
| DIGITS EE MINUS DIGITS { if ($4.length > 4) { YYERROR; }; int exponent = Poincare::Decimal::exponent($1.address, $1.length, nullptr, 0, $4.address, $4.length, true); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, nullptr, 0, false), exponent); }
;
*/
symb : SYMBOL { $$ = new Poincare::Symbol($1); }
symb : SYMBOL { $$ = Poincare::Symbol($1); }
;
term : EMPTY { $$ = $1; }
| symb { $$ = $1; }
| UNDEFINED { $$ = $1; }
| number { $$ = $1; }
/*
| FUNCTION UNDERSCORE LEFT_BRACE lstData RIGHT_BRACE LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; int totalNumberOfArguments = $4->numberOfChildren()+$7->numberOfChildren();
if (!$1->hasValidNumberOfOperands(totalNumberOfArguments)) { delete $1; delete $4; delete $7; YYERROR; };
Poincare::ListData * arguments = new Poincare::ListData();
@@ -194,36 +211,41 @@ $1->setArgument(arguments, totalNumberOfArguments, false);
$4->detachOperands(); delete $4; $7->detachOperands(); delete $7; arguments->detachOperands(); delete arguments;}
| FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; if (!$1->hasValidNumberOfOperands($3->numberOfChildren())) { delete $1; delete $3; YYERROR; } ; $1->setArgument($3, $3->numberOfChildren(), false); $3->detachOperands(); delete $3; }
| FUNCTION LEFT_PARENTHESIS RIGHT_PARENTHESIS { $$ = $1; if (!$1->hasValidNumberOfOperands(0)) { delete $1; YYERROR; } ; }
| LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Parenthesis(terms, false); }
*/
| LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = Poincare::Parenthesis($2); }
/* MATRICES_ARE_DEFINED */
/*
| LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = new Poincare::Matrix($2); delete $2; }
*/
;
bang : term { $$ = $1; }
| term BANG { $$ = new Poincare::Factorial($1, false); }
| term BANG { $$ = Poincare::Factorial($1); }
;
factor : bang { $$ = $1; }
| bang pow %prec IMPLICIT_MULTIPLY { Poincare::Expression * terms[2] = {$1,$2}; $$ = new Poincare::Multiplication(terms, 2, false); }
| bang pow %prec IMPLICIT_MULTIPLY { $$ = Poincare::Multiplication($1, $2); }
;
pow : factor { $$ = $1; }
| bang POW pow { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Power(terms, false); }
| bang POW MINUS pow { Poincare::Expression * terms1[1] = {$4}; Poincare::Expression * terms[2] = {$1,new Poincare::Opposite(terms1, false)}; $$ = new Poincare::Power(terms, false); }
| bang POW pow { $$ = Poincare::Power($1,$3); }
| bang POW MINUS pow { $$ = Poincare::Power($1,Poincare::Opposite($4)); }
;
exp : pow { $$ = $1; }
| exp DIVIDE exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Division(terms, false); }
| exp MULTIPLY exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Multiplication(terms, 2, false); }
| exp MINUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, false); }
| MINUS exp %prec UNARY_MINUS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Opposite(terms, false); }
| exp PLUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Addition(terms, 2, false); }
| exp DIVIDE exp { $$ = Poincare::Division($1,$3); }
| exp MULTIPLY exp { $$ = Poincare::Multiplication($1,$3); }
| exp MINUS exp { $$ = Poincare::Subtraction($1,$3); }
| MINUS exp %prec UNARY_MINUS { $$ = Poincare::Opposite($2); }
| exp PLUS exp { $$ = Poincare::Addition($1;$3); }
;
final_exp : exp { $$ = $1; }
/*
| exp STO symb { if ($3->name() == Poincare::Symbol::SpecialSymbols::Ans) { delete $1; delete $3; YYERROR; } ; Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Store(terms, false); }
| exp EQUAL exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Equal(terms, false); }
;
*/
%%
void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, const char * msg) {

View File

@@ -29,17 +29,8 @@ extern "C" {
#include <stdlib.h>
}
namespace Poincare {
Expression::Type Power::type() const {
return Type::Power;
}
Expression * Power::clone() const {
return new Power(m_operands, true);
}
Expression::Sign Power::sign() const {
if (shouldStopProcessing()) {
return Sign::Unknown;
@@ -110,11 +101,14 @@ int Power::getPolynomialCoefficients(char symbolName, Expression coefficients[])
return -1;
}
Expression * Power::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) {
Expression PowerNode::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) {
return Power(this).setSign(s, context, angleUnit);
}
Expression Power::setSign(Sign s, Context & context, Preferences::AngleUnit angleUnit) {
assert(s == Sign::Positive);
assert(operand(0)->sign() == Sign::Negative);
editableOperand(0)->setSign(Sign::Positive, context, angleUnit);
return this;
assert(childAtIndex(0).sign() == Sign::Negative);
return Power(childAtIndex(0).setSign(Sign::Positive, context, angleUnit), childAtIndex(1));
}
template<typename T>