Poincare: ExpressionBuilder and ExpressionSelector are not PODs anymore

This means we cannot initialize them by using C99-style static init.
C++11 to the rescue: we're using constexpr constructor to build them
statically, without any runtime cost.

This allows us to have private member variables, and a base class.

Change-Id: I0617d196e87f946b48375f42b600eb73e366d87d
This commit is contained in:
Romain Goyet
2016-04-07 15:31:06 +02:00
parent acef4c079e
commit c870c28e61
3 changed files with 110 additions and 27 deletions

View File

@@ -16,7 +16,7 @@ Expression * ExpressionBuilder::build(ExpressionMatch matches[]) {
int numberOfChildrenExpressions = 0;
for (int i=0; i<m_numberOfChildren; i++) {
ExpressionBuilder * child = this->child(i);
ExpressionBuilder * child = (ExpressionBuilder *)this->child(i);
if (child->m_action == ExpressionBuilder::Action::BringUpWildcard) {
for (int j=0; j<matches[child->m_matchIndex].numberOfExpressions(); j++) {
children_expressions[numberOfChildrenExpressions++] =
@@ -62,14 +62,3 @@ Expression * ExpressionBuilder::build(ExpressionMatch matches[]) {
}
return result;
}
// Extrude in a class
ExpressionBuilder * ExpressionBuilder::child(int index) {
assert(index>=0 && index<m_numberOfChildren);
if (index == 0) {
return (this+1); // Pointer arithmetics
} else {
ExpressionBuilder * previousChild = this->child(index-1);
return previousChild+previousChild->m_numberOfChildren+1; // Pointer arithm.
}
}

View File

@@ -2,18 +2,25 @@
#define POINCARE_SIMPLIFY_EXPRESSION_BUILDER_H
#include <poincare/expression.h>
#include "contiguous_tree.h"
#include "expression_match.h"
extern "C" {
#include <stdint.h>
}
class ExpressionBuilder {
typedef Expression * (ExternalGenerator)(Expression ** parameters, int numberOfParameters);
class ExpressionBuilder : public ContiguousTree {
public:
static constexpr ExpressionBuilder BuildFromType(Expression::Type type, uint8_t numberOfChildren);
static constexpr ExpressionBuilder BuildFromTypeAndValue(Expression::Type type, int32_t value, uint8_t numberOfChildren);
static constexpr ExpressionBuilder Clone(uint8_t matchIndex, uint8_t numberOfChildren);
static constexpr ExpressionBuilder BringUpWildcard(uint8_t matchIndex, uint8_t numberOfChildren);
typedef Expression * (ExternalGenerator)(Expression ** parameters, int numberOfParameters);
static constexpr ExpressionBuilder CallExternalGenerator(ExternalGenerator * generator, uint8_t numberOfChildren);
public:
ExpressionBuilder * child(int i);
Expression * build(ExpressionMatch matches[]);
private:
enum class Action {
BuildFromTypeAndValue,
Clone,
@@ -21,6 +28,10 @@ public:
CallExternalGenerator
};
constexpr ExpressionBuilder(Expression::Type type, int32_t integerValue, uint8_t numberOfChildren);
constexpr ExpressionBuilder(Action action, uint8_t matchIndex, uint8_t numberOfChildren);
constexpr ExpressionBuilder(ExternalGenerator * generator, uint8_t numberOfChildren);
Action m_action;
union {
@@ -39,8 +50,67 @@ public:
// m_action == CallExternalGenerator
ExternalGenerator * m_generator;
};
uint8_t m_numberOfChildren;
};
/* Since they have to be evaluated at compile time, constexpr functions are
* implicitely defined inline. Therefore we have to provide their implementation
* in this header. */
constexpr ExpressionBuilder ExpressionBuilder::BuildFromType(
Expression::Type type,
uint8_t numberOfChildren) {
return ExpressionBuilder(type, 0, numberOfChildren);
}
constexpr ExpressionBuilder ExpressionBuilder::BuildFromTypeAndValue(
Expression::Type type,
int32_t value,
uint8_t numberOfChildren) {
return ExpressionBuilder(type, value, numberOfChildren);
}
constexpr ExpressionBuilder ExpressionBuilder::Clone(
uint8_t matchIndex,
uint8_t numberOfChildren) {
return ExpressionBuilder(ExpressionBuilder::Action::Clone, matchIndex, numberOfChildren);
}
constexpr ExpressionBuilder ExpressionBuilder::BringUpWildcard(
uint8_t matchIndex,
uint8_t numberOfChildren) {
return ExpressionBuilder(ExpressionBuilder::Action::BringUpWildcard, matchIndex, numberOfChildren);
}
constexpr ExpressionBuilder ExpressionBuilder::CallExternalGenerator(
ExternalGenerator * generator,
uint8_t numberOfChildren) {
return ExpressionBuilder(generator, numberOfChildren);
}
constexpr ExpressionBuilder::ExpressionBuilder(Expression::Type type,
int32_t integerValue,
uint8_t numberOfChildren)
:
ContiguousTree(numberOfChildren),
m_action(ExpressionBuilder::Action::BuildFromTypeAndValue),
m_expressionType(type),
m_integerValue(integerValue) {
}
constexpr ExpressionBuilder::ExpressionBuilder(Action action,
uint8_t matchIndex,
uint8_t numberOfChildren)
:
ContiguousTree(numberOfChildren),
m_action(action),
m_matchIndex(matchIndex) {
}
constexpr ExpressionBuilder::ExpressionBuilder(ExternalGenerator * generator,
uint8_t numberOfChildren)
:
ContiguousTree(numberOfChildren),
m_action(ExpressionBuilder::Action::CallExternalGenerator),
m_generator(generator) {
}
#endif

View File

@@ -2,21 +2,27 @@
#define POINCARE_SIMPLIFY_EXPRESSION_SELECTOR_H
#include <poincare/expression.h>
#include "contiguous_tree.h"
#include "expression_match.h"
extern "C" {
#include <stdint.h>
}
class ExpressionSelector {
/* Everything must be made public otherwise we cannot static-initialize an
* array of ExpressionSelectors. */
class ExpressionSelector : public ContiguousTree {
public:
enum class Match {
Any,
Type,
Wildcard,
TypeAndValue,
};
static constexpr ExpressionSelector Any(uint8_t numberOfChildren) {
return ExpressionSelector(Match::Any, (Expression::Type)0, 0, numberOfChildren);
}
static constexpr ExpressionSelector Wildcard(uint8_t numberOfChildren) {
return ExpressionSelector(Match::Wildcard, (Expression::Type)0, 0, numberOfChildren);
}
static constexpr ExpressionSelector Type(Expression::Type type, uint8_t numberOfChildren) {
return ExpressionSelector(Match::Type, type, 0, numberOfChildren);
}
static constexpr ExpressionSelector TypeAndValue(Expression::Type type, int32_t value, uint8_t numberOfChildren) {
return ExpressionSelector(Match::TypeAndValue, type, value, numberOfChildren);
}
ExpressionSelector * child(int i);
/* The match function is interesting
* - It returns 0 if the selector didn't match the expression
@@ -25,6 +31,25 @@ public:
* value is zero.
*/
int match(Expression * e, ExpressionMatch * matches);
private:
enum class Match {
Any,
Type,
Wildcard,
TypeAndValue,
};
constexpr ExpressionSelector(Match match,
Expression::Type type,
int32_t integerValue,
uint8_t numberOfChildren)
:
ContiguousTree(numberOfChildren),
m_match(match),
m_expressionType(type),
m_integerValue(integerValue)
{
}
Match m_match;
union {
@@ -41,7 +66,6 @@ public:
};
};
};
uint8_t m_numberOfChildren;
};
#endif