[poincare] Ghost nodes

This commit is contained in:
Léa Saviot
2018-08-03 11:16:50 +02:00
parent 748291d6b8
commit caa12ec49e
11 changed files with 146 additions and 53 deletions

View File

@@ -1,28 +1,22 @@
#ifndef POINCARE_ALLOCATION_FAILED_EXPRESSION_NODE_H
#define POINCARE_ALLOCATION_FAILED_EXPRESSION_NODE_H
#include <poincare/expression_node.h>
#include <poincare/expression_reference.h>
#include <poincare/complex.h>
#include <stdio.h>
#include <poincare/ghost_expression_node.h>
#include <poincare/allocation_failed_layout_node.h>
namespace Poincare {
class AllocationFailedExpressionNode : public ExpressionNode {
class AllocationFailedExpressionNode : public GhostExpressionNode {
public:
// ExpressionNode
Type type() const override { return Type::AllocationFailure; }
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ComplexReference<float>::Undefined(); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ComplexReference<double>::Undefined(); }
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override;
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { return AllocationFailedLayoutRef(); }
// TreeNode
size_t size() const override { return sizeof(AllocationFailedExpressionNode); }
#if TREE_LOG
const char * description() const override { return "Allocation Failed"; }
const char * description() const override { return "AllocationFailedExpression"; }
#endif
int numberOfChildren() const override { return 0; }
bool isAllocationFailure() const override { return true; }
};

View File

@@ -1,47 +1,19 @@
#ifndef POINCARE_ALLOCATION_FAILED_LAYOUT_NODE_H
#define POINCARE_ALLOCATION_FAILED_LAYOUT_NODE_H
#include "layout_node.h"
#include "layout_reference.h"
#include "layout_cursor.h"
#include "ghost_layout_node.h"
namespace Poincare {
class AllocationFailedLayoutNode : public LayoutNode {
class AllocationFailedLayoutNode : public GhostLayoutNode {
public:
// LayoutNode
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
assert(false);
return 0;
}
void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override {}
void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override {}
LayoutCursor equivalentCursor(LayoutCursor * cursor) override { return LayoutCursor(); }
void deleteBeforeCursor(LayoutCursor * cursor) override {}
bool isAllocationFailure() const override { return true; }
using GhostLayoutNode::GhostLayoutNode;
// TreeNode
int numberOfChildren() const override { return 0; }
bool isAllocationFailure() const override { return true; }
size_t size() const override { return sizeof(AllocationFailedLayoutNode); }
#if TREE_LOG
const char * description() const override { return "Allocation Failed"; }
const char * description() const override { return "AllocationFailedLayout"; }
#endif
protected:
// LayoutNode
KDSize computeSize() override { return KDSizeZero; }
KDCoordinate computeBaseline() override { return 0; }
KDPoint positionOfChild(LayoutNode * child) override {
assert(false);
return KDPointZero;
}
private:
bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override { return false; }
bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor, bool force) override { return false; }
bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force) override { return false; }
void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {}
};
class AllocationFailedLayoutRef : public LayoutReference {

View File

@@ -35,6 +35,11 @@ public:
virtual EvaluationReference<T> transpose() const = 0;
// TreeNode
TreeNode * ghostStaticNode() override {
assert(false);
return FailedAllocationStaticNode();
}
static TreeNode * FailedAllocationStaticNode();
TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); }

View File

@@ -14,14 +14,15 @@ namespace Poincare {
* ExpressionRef. */
class ExpressionNode : public SerializableNode {
friend class ApproximationEngine;
friend class SymbolNode;
friend class ApproximationEngine;
friend class SymbolNode;
friend class NAryExpressionNode;
public:
enum class Type : uint8_t {
AllocationFailure = 0,
Undefined = 1,
Integer = 2,
Ghost = 0,
AllocationFailure = 1,
Undefined = 2,
Integer = 3,
Rational,
Decimal,
Float,
@@ -86,6 +87,10 @@ public:
PredictionInterval,
EmptyExpression
};
/* Ghost */
static TreeNode * GhostStaticNode();
TreeNode * ghostStaticNode() override { return GhostStaticNode(); }
/* Allocation failure */
static TreeNode * FailedAllocationStaticNode();
TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); }

View File

@@ -0,0 +1,43 @@
#ifndef POINCARE_GHOST_EXPRESSION_NODE_H
#define POINCARE_GHOST_EXPRESSION_NODE_H
#include <poincare/expression_node.h>
#include <poincare/expression_reference.h>
#include <poincare/complex.h>
#include <poincare/ghost_layout_ref.h>
#include <stdio.h>
namespace Poincare {
class GhostExpressionNode : public ExpressionNode {
public:
// ExpressionNode
Type type() const override { return Type::Ghost; }
EvaluationReference<float> approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ComplexReference<float>::Undefined(); }
EvaluationReference<double> approximate(DoublePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ComplexReference<double>::Undefined(); }
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { return GhostLayoutRef(); }
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = 0) const override {
int descriptionLength = strlen(description()) + 1;
return strlcpy(buffer, description(), bufferSize < descriptionLength ? bufferSize : descriptionLength);
}
// TreeNode
size_t size() const override { return sizeof(GhostExpressionNode); }
#if TREE_LOG
const char * description() const override { return "GhostExpression"; }
#endif
int numberOfChildren() const override { return 0; }
};
class GhostExpressionRef : public ExpressionReference {
public:
GhostExpressionRef() : ExpressionReference() {
TreeNode * node = TreePool::sharedPool()->createTreeNode<GhostExpressionNode>();
m_identifier = node->identifier();
}
GhostExpressionRef(TreeNode * n) : ExpressionReference(n) {}
};
}
#endif

View File

@@ -0,0 +1,58 @@
#ifndef POINCARE_GHOST_LAYOUT_NODE_H
#define POINCARE_GHOST_LAYOUT_NODE_H
#include "layout_node.h"
#include "layout_reference.h"
#include "layout_cursor.h"
namespace Poincare {
class GhostLayoutNode : public LayoutNode {
public:
// LayoutNode
int writeTextInBuffer(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
assert(false);
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 {}
LayoutCursor equivalentCursor(LayoutCursor * cursor) override { return LayoutCursor(); }
void deleteBeforeCursor(LayoutCursor * cursor) override {}
// TreeNode
int numberOfChildren() const override { return 0; }
size_t size() const override { return sizeof(GhostLayoutNode); }
#if TREE_LOG
const char * description() const override { return "GhostLayout"; }
#endif
protected:
// LayoutNode
KDSize computeSize() override { return KDSizeZero; }
KDCoordinate computeBaseline() override { return 0; }
KDPoint positionOfChild(LayoutNode * child) override {
assert(false);
return KDPointZero;
}
private:
bool willAddSibling(LayoutCursor * cursor, LayoutNode * sibling, bool moveCursor) override { return false; }
bool willReplaceChild(LayoutNode * oldChild, LayoutNode * newChild, LayoutCursor * cursor, bool force) override { return false; }
bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force) override { return false; }
void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override {}
};
class GhostLayoutRef : public LayoutReference {
public:
GhostLayoutRef() : LayoutReference() {
TreeNode * node = TreePool::sharedPool()->createTreeNode<GhostLayoutNode>();
m_identifier = node->identifier();
}
GhostLayoutRef(TreeNode * n) : LayoutReference(n) {}
};
}
#endif

View File

@@ -50,6 +50,8 @@ public:
virtual void invalidAllSizesPositionsAndBaselines();
// TreeNode
static TreeNode * GhostStaticNode();
TreeNode * ghostStaticNode() override { return GhostStaticNode(); }
static TreeNode * FailedAllocationStaticNode();
TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); }

View File

@@ -46,9 +46,9 @@ public:
// Allocation failure
virtual bool isAllocationFailure() const { return false; }
virtual TreeNode * failedAllocationStaticNode() = 0;
int allocationFailureNodeIdentifier() {
return failedAllocationStaticNode()->identifier();
}
int allocationFailureNodeIdentifier() { return failedAllocationStaticNode()->identifier(); }
virtual TreeNode * ghostStaticNode() = 0;
int ghostNodeIdentifier() { return ghostStaticNode()->identifier(); }
// Node operations
void retain() {

View File

@@ -85,7 +85,7 @@ public:
private:
constexpr static int BufferSize = 1024;//2048;
constexpr static int MaxNumberOfNodes = BufferSize/sizeof(TreeNode);
constexpr static int MaxNumberOfStaticNodes = 2; // ExpressionNode, LayoutNode
constexpr static int MaxNumberOfStaticNodes = 5; // GhostLayoutNode, AllocationFailedLayoutNode, GhostExpressionNode, AllocationFailedExpressionNode, AllocationFailedEvaluationNode
// TreeNode
void discardTreeNode(TreeNode * node) {

View File

@@ -1,9 +1,16 @@
#include <poincare/expression_node.h>
#include <poincare/undefined.h>
#include <poincare/ghost_expression_node.h>
#include <poincare/allocation_failed_expression_node.h>
namespace Poincare {
TreeNode * ExpressionNode::GhostStaticNode() {
static GhostExpressionNode GhostNode;
TreePool::sharedPool()->registerStaticNodeIfRequired(&GhostNode);
return &GhostNode;
}
TreeNode * ExpressionNode::FailedAllocationStaticNode() {
static AllocationFailedExpressionNode FailureNode;
TreePool::sharedPool()->registerStaticNodeIfRequired(&FailureNode);

View File

@@ -1,5 +1,6 @@
#include <poincare/layout_node.h>
#include <poincare/allocation_failed_layout_node.h>
#include <poincare/ghost_layout_node.h>
#include <poincare/horizontal_layout_node.h>
#include <poincare/layout_cursor.h>
#include <poincare/layout_reference.h>
@@ -67,6 +68,12 @@ void LayoutNode::invalidAllSizesPositionsAndBaselines() {
// TreeNode
TreeNode * LayoutNode::GhostStaticNode() {
static GhostStaticNode GhostNode;
TreePool::sharedPool()->registerStaticNodeIfRequired(&GhostNode);
return &GhostNode;
}
TreeNode * LayoutNode::FailedAllocationStaticNode() {
static AllocationFailedLayoutNode FailureNode;
TreePool::sharedPool()->registerStaticNodeIfRequired(&FailureNode);