[poincare] Clean the simplification folder

This commit is contained in:
Romain Goyet
2017-09-22 12:07:55 +02:00
parent 0c140cc4c7
commit 84e4e80a6d
45 changed files with 273 additions and 696 deletions

View File

@@ -1,6 +1,6 @@
SFLAGS += -Ipoincare/include
include poincare/src/simplify/Makefile
include poincare/src/simplification/Makefile
objs += $(addprefix poincare/src/,\
absolute_value.o\

View File

@@ -1,6 +1,6 @@
#include poincare/src/simplify/rules_generation/Makefile
dir=poincare/src/simplify
dir=poincare/src/simplification
$(dir)/rules.cpp: $(RULEGEN) $(dir)/rules.pr
@echo "RULEGEN $@"
@@ -9,11 +9,10 @@ $(dir)/rules.cpp: $(RULEGEN) $(dir)/rules.pr
products += $(dir)/rules.cpp
objs += $(addprefix $(dir)/,\
combination.o \
expression.o \
expression_simplify.o \
rule.o \
integer_addition.o \
merge_addition.o \
type_selector.o \
selector.o \
selector/combination.o \
selector/selector.o \
selector/type_selector.o \
transform/merge_addition_transform.o \
)

View File

@@ -35,8 +35,8 @@ void Expression::simplify(Expression ** e) {
root.sort();
// Only unconditional simplify
int ruleIndex = 0;
while (ruleIndex < DemoRuleSet.numberOfRules()) {
const Rule * rule = DemoRuleSet.ruleAtIndex(ruleIndex++);
while (ruleIndex < Simplification::DemoRuleSet.numberOfRules()) {
const Simplification::Rule * rule = Simplification::DemoRuleSet.ruleAtIndex(ruleIndex++);
if (rule->apply(&root)) {
root.sort();
std::cout << "-----" << std::endl;
@@ -48,22 +48,4 @@ void Expression::simplify(Expression ** e) {
*e = (Expression *)(root.operand(0));
}
#if 0
Expression * Expression::simplify() {
sort();
// Only unconditional simplify
int ruleIndex = 0;
while (ruleIndex < DemoRuleSet.numberOfRules()) {
const Rule * rule = DemoRuleSet.ruleAtIndex(ruleIndex++);
if (rule->apply(this)) {
this->sort();
std::cout << "-----" << std::endl;
print_expression(this, 0);
std::cout << "-----" << std::endl;
ruleIndex = 0;
}
}
}
#endif
}

View File

@@ -0,0 +1 @@
Addition(Integer.a,Integer.b) -> IntegerAddition

View File

@@ -1,6 +1,7 @@
#include "rule.h"
namespace Poincare {
namespace Simplification {
bool Rule::apply(Expression * e) const {
if (immediateApply(e)) {
@@ -28,3 +29,4 @@ bool Rule::immediateApply(Expression * e) const {
}
}
}

View File

@@ -1,10 +1,11 @@
#ifndef POINCARE_SIMPLIFY_RULE_H
#define POINCARE_SIMPLIFY_RULE_H
#ifndef POINCARE_SIMPLIFICATION_RULE_H
#define POINCARE_SIMPLIFICATION_RULE_H
#include "selector.h"
#include "transform.h"
#include "selector/selector.h"
#include "transform/transform.h"
namespace Poincare {
namespace Simplification {
class Rule {
public:
@@ -18,6 +19,7 @@ private:
const Transform * m_transform;
};
}
}
#endif

View File

@@ -1,5 +1,5 @@
#ifndef POINCARE_SIMPLIFY_RULES_H
#define POINCARE_SIMPLIFY_RULES_H
#ifndef POINCARE_SIMPLIFICATION_RULES_H
#define POINCARE_SIMPLIFICATION_RULES_H
#include "simplification.h"

View File

@@ -1,5 +1,5 @@
#ifndef POINCARE_SIMPLIFY_RULES_GENERATION_NODE_H
#define POINCARE_SIMPLIFY_RULES_GENERATION_NODE_H
#ifndef POINCARE_SIMPLIFICATION_RULES_GENERATION_NODE_H
#define POINCARE_SIMPLIFICATION_RULES_GENERATION_NODE_H
class Rule;

View File

@@ -1,5 +1,5 @@
#ifndef POINCARE_SIMPLIFY_RULES_GENERATION_RULE_H
#define POINCARE_SIMPLIFY_RULES_GENERATION_RULE_H
#ifndef POINCARE_SIMPLIFICATION_RULES_GENERATION_RULE_H
#define POINCARE_SIMPLIFICATION_RULES_GENERATION_RULE_H
#include "node.h"

View File

@@ -1,13 +1,12 @@
#ifndef POINCARE_SIMPLIFY_RULESET_H
#define POINCARE_SIMPLIFY_RULESET_H
#ifndef POINCARE_SIMPLIFICATION_RULESET_H
#define POINCARE_SIMPLIFICATION_RULESET_H
#include "rule.h"
#include "type_selector.h"
#include "integer_addition.h"
#include "merge_addition.h"
#include "transform/subtraction_transform.h"
#include "selector/type_selector.h"
#include "transform/merge_addition_transform.h"
namespace Poincare {
namespace Simplification {
class RuleSet {
public:
@@ -21,6 +20,7 @@ private:
int m_numberOfRules;
};
#if 0
//R0: Int + Int -> AdditionDeInt
constexpr TypeSelector r0s0(Expression::Type::Integer, 0);
constexpr TypeSelector r0s1(Expression::Type::Integer, 1);
@@ -28,6 +28,7 @@ constexpr const Selector * r0s2c[] = {&r0s0, &r0s1};
constexpr TypeSelector r0s2(Expression::Type::Addition, 2, r0s2c, 2);
constexpr IntegerAddition r0t;
constexpr Rule r0(&r0s2, &r0t);
#endif
#if 0
@@ -65,14 +66,15 @@ constexpr Rule r0(&r0s2, &r0t);
constexpr TypeSelector r1s0(Expression::Type::Addition, 0);
constexpr const Selector * r1s1c[] = {&r1s0};
constexpr TypeSelector r1s1(Expression::Type::Addition, 1, r1s1c, 1);
constexpr MergeAddition r1t;
constexpr MergeAdditionTransform r1t;
constexpr Rule r1(&r1s1, &r1t);
// RuleSet
//constexpr Rule rules[2] = {R3::rule, r1, r0, R2::rule};
constexpr Rule rules[2] = {r1, r0};
constexpr RuleSet DemoRuleSet(rules, 2);
constexpr Rule rules[1] = {r1};
constexpr RuleSet DemoRuleSet(rules, 1);
}
}
#endif

View File

@@ -1,9 +1,10 @@
#ifndef POINCARE_SIMPLIFY_ANY_SELECTOR_H
#define POINCARE_SIMPLIFY_ANY_SELECTOR_H
#ifndef POINCARE_SIMPLIFICATION_SELECTOR_ANY_SELECTOR_H
#define POINCARE_SIMPLIFICATION_SELECTOR_ANY_SELECTOR_H
#include "selector.h"
namespace Poincare {
namespace Simplification {
class AnySelector : public Selector {
public:
@@ -11,6 +12,7 @@ public:
bool acceptsLocationInCombination(const Combination * combination, int location) const override;
};
}
}
#endif

View File

@@ -2,6 +2,7 @@
#include <assert.h>
namespace Poincare {
namespace Simplification {
Combination::Combination(const Selector * const * selectors, int numberOfSelectors, const Expression * rootExpression) :
m_selectors(selectors),
@@ -64,3 +65,4 @@ bool Combination::next() {
}
}
}

View File

@@ -1,10 +1,11 @@
#ifndef POINCARE_SIMPLIFY_COMBINATION_H
#define POINCARE_SIMPLIFY_COMBINATION_H
#ifndef POINCARE_SIMPLIFICATION_SELECTOR_COMBINATION_H
#define POINCARE_SIMPLIFICATION_SELECTOR_COMBINATION_H
#include <poincare/expression.h>
#include "selector.h"
namespace Poincare {
namespace Simplification {
/* Combination is the association of two tables: a selectors table and an expressions
* table.
@@ -35,6 +36,7 @@ private:
bool m_firstIteration;
};
}
}
#endif

View File

@@ -0,0 +1,21 @@
#ifndef POINCARE_SIMPLIFICATION_SAME_AS_SELECTOR_H
#define POINCARE_SIMPLIFICATION_SAME_AS_SELECTOR_H
#include "selector.h"
namespace Poincare {
namespace Simplification {
class SameAsSelector : public Selector {
public:
constexpr SameAsSelector(int originalIndex, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0) :
Selector(captureIndex, children, numberOfChildren), m_originalIndex(originalIndex) {}
bool acceptsLocationInCombination(const Combination * combination, int location) const override;
private:
int m_originalIndex;
};
}
}
#endif

View File

@@ -3,6 +3,7 @@
#include <assert.h>
namespace Poincare {
namespace Simplification {
bool Selector::match(const Expression * e, Expression ** captures) const {
// Si pour commencer, e ne correspond pas mon petit test moi perso, c'est mort!
@@ -48,3 +49,4 @@ bool Selector::match(const Expression * e, Expression ** captures) const {
}
}
}

View File

@@ -1,21 +1,17 @@
#ifndef POINCARE_SIMPLIFY_SELECTOR_H
#define POINCARE_SIMPLIFY_SELECTOR_H
#ifndef POINCARE_SIMPLIFICATION_SELECTOR_SELECTOR_H
#define POINCARE_SIMPLIFICATION_SELECTOR_SELECTOR_H
#include <poincare/expression.h>
namespace Poincare {
namespace Simplification {
class Combination;
class Selector {
public:
constexpr Selector(int captureIndex = -1, const Selector * const * children = nullptr, int numberOfChildren = 0) :
m_captureIndex(captureIndex),
m_children(children),
m_numberOfChildren(numberOfChildren)
{
};
m_captureIndex(captureIndex), m_children(children), m_numberOfChildren(numberOfChildren) {}
virtual bool acceptsLocationInCombination(const Combination * combination, int location) const = 0;
virtual bool immediateMatch(const Expression * e) const = 0;
bool match(const Expression * e, Expression ** captures) const;
@@ -25,6 +21,7 @@ private:
int m_numberOfChildren;
};
}
}
#endif

View File

@@ -0,0 +1,21 @@
#ifndef POINCARE_SIMPLIFICATION_SELECTOR_TYPE_AND_VALUE_SELECTOR_H
#define POINCARE_SIMPLIFICATION_SELECTOR_TYPE_AND_VALUE_SELECTOR_H
#include "selector.h"
namespace Poincare {
namespace Simplification {
class TypeAndValueSelector : public Selector {
public:
constexpr TypeAndValueSelector(Expression::Type type, int value, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0) : Selector(captureIndex, children, numberOfChildren), m_type(type), m_value(value) { }
bool acceptsLocationInCombination(const Combination * combination, int location) const override;
private:
Expression::Type m_type;
int m_value;
};
}
}
#endif

View File

@@ -2,6 +2,7 @@
#include "combination.h"
namespace Poincare {
namespace Simplification {
bool TypeSelector::immediateMatch(const Expression * e) const {
return (e->type() == m_type);
@@ -22,3 +23,4 @@ bool TypeSelector::acceptsLocationInCombination(const Combination * combination,
}
}
}

View File

@@ -1,21 +1,22 @@
#ifndef POINCARE_SIMPLIFY_TYPE_SELECTOR_H
#define POINCARE_SIMPLIFY_TYPE_SELECTOR_H
#ifndef POINCARE_SIMPLIFICATION_SELECTOR_TYPE_SELECTOR_H
#define POINCARE_SIMPLIFICATION_SELECTOR_TYPE_SELECTOR_H
#include "selector.h"
namespace Poincare {
namespace Simplification {
class TypeSelector : public Selector {
public:
constexpr TypeSelector(Expression::Type type, int captureIndex = -1, const Selector * const * children = nullptr, int numberOfChildren = 0) :
Selector(captureIndex, children, numberOfChildren),
m_type(type) {};
Selector(captureIndex, children, numberOfChildren), m_type(type) {}
bool immediateMatch(const Expression * e) const override;
bool acceptsLocationInCombination(const Combination * combination, int location) const override;
private:
Expression::Type m_type;
};
}
}
#endif

View File

@@ -1,9 +1,10 @@
#ifndef POINCARE_SIMPLIFY_INTEGER_ADDITION_H
#define POINCARE_SIMPLIFY_INTEGER_ADDITION_H
#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_INTEGER_ADDITION_H
#define POINCARE_SIMPLIFICATION_TRANSFORM_INTEGER_ADDITION_H
#include "transform.h"
namespace Poincare {
namespace Simplification {
class IntegerAddition : public Transform {
public:
@@ -11,6 +12,7 @@ public:
void apply(Expression * root, Expression * captures[]) const override;
};
}
}
#endif

View File

@@ -0,0 +1,17 @@
#ifndef POINCARE_SIMPLIFICATION_INTEGER_PAIR_TRANSFORM_H
#define POINCARE_SIMPLIFICATION_INTEGER_PAIR_TRANSFORM_H
#include "transform.h"
namespace Poincare {
class IntegerPairTransform : public Transform {
public:
constexpr IntegerPairTransform() {};
void apply(Expression * root, Expression * captures[]) const override;
virtual Integer process(const Integer & a, const Integer & b) const = 0;
};
}
#endif

View File

@@ -1,10 +1,11 @@
#include "merge_addition.h"
#include "merge_addition_transform.h"
#include <assert.h>
#include <poincare/addition.h>
namespace Poincare {
namespace Simplification {
void MergeAddition::apply(Expression * root, Expression * captures[]) const {
void MergeAdditionTransform::apply(Expression * root, Expression * captures[]) const {
assert(captures[0]->type() == Expression::Type::Addition);
assert(captures[1]->type() == Expression::Type::Addition);
assert(captures[1] == root);
@@ -18,3 +19,4 @@ void MergeAddition::apply(Expression * root, Expression * captures[]) const {
}
}
}

View File

@@ -0,0 +1,18 @@
#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_MERGE_ADDITION_TRANSFORM_H
#define POINCARE_SIMPLIFICATION_TRANSFORM_MERGE_ADDITION_TRANSFORM_H
#include "transform.h"
namespace Poincare {
namespace Simplification {
class MergeAdditionTransform : public Transform {
public:
constexpr MergeAdditionTransform() {};
void apply(Expression * root, Expression * captures[]) const override;
};
}
}
#endif

View File

@@ -0,0 +1,69 @@
// Match a pattern Int*Int^-1
// can match pow(6,-1)*ln(x)*4. We want 2/3.ln(x).
bool SimplificationIntegerFraction(Multiplication * multiplication, Integer * numerator, Power * power, Integer * denominator) {
Integer gcd = Arithmetic::GCD(*numerator, *denominator);
if (gcd.isEqualTo(Integer(1))) {
return false;
}
IntegerDivision numeratorDivision(*numerator, gcd);
assert(numeratorDivision.remainder().isEqualTo(Integer(0)));
IntegerDivision denominatorDivision(*denominator, gcd);
assert(denominatorDivision.remainder().isEqualTo(Integer(0)));
multiplication->replaceOperand(numerator, numeratorDivision.quotient().clone());
power->replaceOperand(denominator, denominatorDivision.quotient().clone());
return true;
}
bool SimplificationIntegerAddition(Addition * addition, Integer * first, Integer * second) {
Integer result = Integer::Addition(*first, *second);
if (addition->numberOfOperands() == 2) {
addition->parent()->replaceOperand(addition, result.clone());
} else {
assert(addition->numberOfOperands() > 2);
addition->replaceOperand(first, result.clone());
addition->removeOperand(second);
}
return true;
}
// cos(pi*3*x)
void SimplificationCosineIntegerPi(Cosine * cosine, Multiplication * multiplication, Integer * integer) {
if (multiplication->numberOfChildren() != 2) {
// We only handle cases with cos(Integer*Pi)
return false;
}
}
// OK, on fait une classe Start qui hérite de Expression
//
Expression * simplify() {
}
class Start : StaticHierarchy<1> {
public:
Start(Expression * e) : StaticHierarchy<1>({e}, false);
void simplify();
};
void maFonction() {
}
class SimplifiableExpression : public Expression {
};
void autreFonction() {
Expression * e = Parse("1+2+3");
Expresion * simplified = e->simplify();
}
class Expression {
void simplify() {
assert(type() == Start);
//Expression * start = new Start(this);
//return start->simplify()->firstChild();
}
};

View File

@@ -0,0 +1,40 @@
#include "subtraction_transform.h"
#include <assert.h>
#include <poincare/addition.h>
#include <poincare/multiplication.h>
#include <poincare/subtraction.h>
#include <utility>
namespace Poincare {
void SubtractionTransform::apply(Expression * root, Expression * captures[]) const {
assert(captures[0]->type() == Expression::Type::Subtraction);
assert(captures[0] == root);
Subtraction * s = (subtraction *)(root);
Expression * operands[] = {
new Integer(-1),
s->operands(1)
};
Multiplication * m = new Multiplication(operands, 2, false);
Addition * a = new Addition(
s->parent()->replaceOperand(s,
Integer resultOnStack = i1->add(*i2);
Integer * r = new Integer(std::move(resultOnStack));
//r->add(resultOnStack);
// FIXME: Beeeeuargl
if (a->numberOfOperands() == 2) {
((Hierarchy *)a->parent())->replaceOperand(a, r);
} else {
assert(a->numberOfOperands() > 2);
a->replaceOperand(i1, r);
a->removeOperand(i2);
}
}
}

View File

@@ -0,0 +1,16 @@
#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_SUBTRACTION_TRANSFORM_H
#define POINCARE_SIMPLIFICATION_TRANSFORM_SUBTRACTION_TRANSFORM_H
#include "../transform.h"
namespace Poincare {
class SubtractionTransform : public Transform {
public:
constexpr SubtractionTransform() {};
void apply(Expression * root, Expression * captures[]) const override;
};
}
#endif

View File

@@ -1,15 +1,17 @@
#ifndef POINCARE_SIMPLIFY_TRANSFORM_H
#define POINCARE_SIMPLIFY_TRANSFORM_H
#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_TRANSFORM_H
#define POINCARE_SIMPLIFICATION_TRANSFORM_TRANSFORM_H
#include <poincare/expression.h>
namespace Poincare {
namespace Simplification {
class Transform {
public:
virtual void apply(Expression * root, Expression * captures[]) const = 0;
};
}
}
#endif

View File

@@ -1,90 +0,0 @@
#include "expression_builder.h"
#include <poincare/addition.h>
#include <poincare/integer.h>
#include <poincare/multiplication.h>
#include <poincare/symbol.h>
extern "C" {
#include <assert.h>
}
namespace Poincare {
Expression * ExpressionBuilder::build(ExpressionMatch matches[]) {
Expression * children_expressions[255]; // FIXME: <- The sized can be given by the compiler
//Expression * children_expressions = malloc;
// That malloc can be avoided: we can give an upper bound
// Afer we've finished processing the rules
// That upper bound is likely to be very small (3, currently)
int numberOfChildrenExpressions = 0;
for (int i=0; i<m_numberOfChildren; i++) {
ExpressionBuilder * child = this->child(i);
if (child->m_action == ExpressionBuilder::Action::BringUpWildcard) {
for (int j=0; j<matches[child->m_matchIndex].numberOfExpressions(); j++) {
children_expressions[numberOfChildrenExpressions++] =
matches[child->m_matchIndex].expression(j)->clone();
}
} else {
children_expressions[numberOfChildrenExpressions++] = child->build(matches);
}
}
Expression * result = nullptr;
switch(m_action) {
case ExpressionBuilder::Action::BuildFromType:
switch(m_expressionType) {
case Expression::Type::Addition:
/* The children do not need to be cloned as they already have been
* before. */
result = new Addition(children_expressions, false);
break;
case Expression::Type::Multiplication:
/* The children do not need to be cloned as they already have been
* before. */
result = new Multiplication(children_expressions, false);
break;
default:
assert(false);
break;
}
break;
case ExpressionBuilder::Action::BuildFromTypeAndValue:
switch(m_expressionType) {
case Expression::Type::Integer:
result = new Integer(m_integerValue);
break;
case Expression::Type::Symbol:
result = new Symbol(m_symbolName);
break;
default:
assert(false);
break;
}
break;
case ExpressionBuilder::Action::BringUpWildcard:
// Build should never be called on BringUpWildcard action directly
assert(false);
break;
case ExpressionBuilder::Action::Clone:
// It only makes sense to clone if the match has a single expression!
assert(matches[m_matchIndex].numberOfExpressions() == 1);
result = matches[m_matchIndex].expression(0)->clone();
break;
case ExpressionBuilder::Action::CallExternalGenerator:
result = m_generator(children_expressions, numberOfChildrenExpressions);
break;
}
return result;
}
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

@@ -1,47 +0,0 @@
#include "expression_match.h"
extern "C" {
#include <assert.h>
#include <stdlib.h>
}
namespace Poincare {
ExpressionMatch::ExpressionMatch() {
m_numberOfExpressions = 0;
m_expressions = nullptr;
}
ExpressionMatch::ExpressionMatch(const Expression ** expressions, int numberOfExpressions) {
m_numberOfExpressions = numberOfExpressions;
m_expressions = (const Expression**) malloc(m_numberOfExpressions * sizeof(Expression*));
for (int i(0); i<numberOfExpressions; i++) {
m_expressions[i] = expressions[i];
}
}
ExpressionMatch::~ExpressionMatch() {
if (m_numberOfExpressions != 0) {
free(m_expressions);
}
}
const Expression * ExpressionMatch::expression(int i) {
assert(i < m_numberOfExpressions);
return m_expressions[i];
}
int ExpressionMatch::numberOfExpressions() {
return m_numberOfExpressions;
}
ExpressionMatch& ExpressionMatch::operator=(ExpressionMatch&& other) {
m_numberOfExpressions = other.m_numberOfExpressions;
// Here we make sure that the memory containing the expressions is not freed
// in order to avoid a double free
other.m_numberOfExpressions = 0;
m_expressions = other.m_expressions;
return *this;
}
}

View File

@@ -1,332 +0,0 @@
extern "C" {
#include <assert.h>
#include <stdlib.h>
}
#include <poincare/integer.h>
#include <poincare/symbol.h>
#include "expression_selector.h"
namespace Poincare {
const uint8_t kUnmatched = 0xff;
int ExpressionSelector::numberOfNonWildcardChildren() {
bool hasWildcard = child(m_numberOfChildren-1)->m_match == ExpressionSelector::Match::Wildcard;
int numberOfChildren = m_numberOfChildren;
if (hasWildcard) {
numberOfChildren--;
}
return numberOfChildren;
}
int ExpressionSelector::match(const Expression * e, ExpressionMatch * matches) {
return this->match(e, matches, 0);
}
int ExpressionSelector::match(const Expression * e, ExpressionMatch * matches, int offset) {
int numberOfMatches = 0;
// Does the current node match?
switch(m_match) {
case ExpressionSelector::Match::Any:
// Yes, it always does!
break;
case ExpressionSelector::Match::Type:
if (e->type() != m_expressionType) {
return 0;
}
break;
case ExpressionSelector::Match::TypeAndValue:
if (e->type() != m_expressionType) {
return 0;
}
switch(e->type()) {
case Expression::Type::Integer:
{
Integer integer = Integer(m_integerValue);
if (!e->valueEquals(&integer)) {
return 0;
}
}
break;
case Expression::Type::Symbol:
{
Symbol symbol = Symbol(m_symbolName);
if (!e->valueEquals(&symbol)) {
return 0;
}
}
break;
default:
// Symbol and Integer are the only expressions which should be matched
// with a value.
assert(false);
break;
}
break;
case ExpressionSelector::Match::Wildcard:
/* This should not happen as a wildcard should be matched _before_ */
assert(false);
break;
case ExpressionSelector::Match::SameAs:
/* Here we assume that the match can only have a single child, as we
* don't want to match on wildcards. */
assert(matches[m_integerValue].numberOfExpressions() == 1);
if (!e->isEquivalentTo((Expression *)matches[m_sameAsPosition].expression(0))) {
return 0;
}
break;
}
// The current node does match. Let's add it to our matches
matches[offset + numberOfMatches++] = ExpressionMatch(&e, 1);
if (m_numberOfChildren != 0) {
int numberOfChildMatches = 0;
if (!e->isCommutative()) {
numberOfChildMatches = sequentialMatch(e, matches, offset+numberOfMatches);
} else {
numberOfChildMatches = commutativeMatch(e, matches, offset+numberOfMatches);
}
// We check whether the children matched or not.
if (numberOfChildMatches == 0) {
return 0;
} else {
numberOfMatches += numberOfChildMatches;
}
}
return numberOfMatches;
}
/* This tries to match the children selector sequentialy */
int ExpressionSelector::sequentialMatch(const Expression * e,
ExpressionMatch * matches, int offset) {
int numberOfMatches = 0;
for (int i=0; i<m_numberOfChildren; i++) {
ExpressionSelector * childSelector = child(i);
const Expression * childExpression = e->operand(i);
if (childSelector->m_match == ExpressionSelector::Match::Wildcard) {
assert(false); // There should not be a wildcard for non commutative op.
} else {
int numberOfChildMatches = childSelector->match(
childExpression,
matches,
offset+numberOfMatches);
if (numberOfChildMatches == 0) {
return 0;
} else {
numberOfMatches += numberOfChildMatches;
}
}
}
return numberOfMatches;
}
/* This iterates over the combinations of possible matches in the children of
* a selector and then writes the output ExpressionMatch to matches just like
* match would do.
*/
int ExpressionSelector::commutativeMatch(const Expression * e, ExpressionMatch * matches, int offset) {
// If we have more children to match than the expression has, we cannot match.
if (e->numberOfOperands() < m_numberOfChildren) {
return 0;
}
bool hasWildcard = child(m_numberOfChildren-1)->m_match == ExpressionSelector::Match::Wildcard;
uint8_t * selectorMatched = (uint8_t *)malloc(e->numberOfOperands()*sizeof(uint8_t));
/* Initialize the selectors matched to unmatched (0xff), here we assume that
* we never have more than 255 direct children selector. */
assert(this->m_numberOfChildren<kUnmatched);
for (int i(0); i<e->numberOfOperands(); i++) {
selectorMatched[i] = kUnmatched;
}
/* TODO: This one's size can be determined by the compiler as this is the
* maximum number of direct children selectors. */
uint8_t expressionMatched[5];
/* If we have a wildcard we do not want to try to match it to an expression
* yet. */
int numberOfChildren = this->numberOfNonWildcardChildren();
if (!canCommutativelyMatch(e, matches, selectorMatched, numberOfChildren, offset)) {
free(selectorMatched);
return 0;
}
/* Note that we need this indirection because the order in which the selectors
* are defined is significant.
*
* We can see that in the following example:
* Here we try to match:
* +
* / \
* + w
* /
* w
* Onto:
* +
* / \
* 4 +
* / \
* 2 3
*
* Since + is commutative they do match which is nice.
* The issue here is that the matches are expected in a certain order by the
* builder, here the order expected is:
* 0
* / \
* 1 3
* /
* 2
* But The nodes of the expressions are matched in this order:
* 0
* / \
* 1 2
* \
* 3
* Which is not what we want, thus remembering which selector matched which
* expression allows us to put the match in the proper order.
* We got an expression -> selector relationship, here we are just inversting
* it to get the selector -> expression relationship that we want. */
for (int i = 0; i<e->numberOfOperands(); i++) {
if (selectorMatched[i] != kUnmatched) {
expressionMatched[selectorMatched[i]] = i;
}
}
/* Here we recursively write the matches of each selector in the matches
* table.
*
* Using the example in the previous comment we would write
* | + | + | (Integer(2),Integer(3)) | Integer(4) |
*
* The pointer arithmetic with numberOfMatches, allows us to know how many
* matches a selector has written.
* Using the previous example, the part with
* +
* |
* w
* would write two matches:
* + and (Integer(2), Integer(3))
* whereas:
* w
* would only write one:
* Integer(4) */
int numberOfMatches = 0;
for (int i(0); i<numberOfChildren; i++) {
int numberOfChildMatches = child(i)->match(
e->operand(expressionMatched[i]),
matches,
offset + numberOfMatches);
assert(numberOfChildMatches > 0);
numberOfMatches += numberOfChildMatches;
}
if (hasWildcard) {
/* We allocate a table of Expression* the size of the number of unmatched
* operands. */
const Expression ** local_expr = (const Expression**) malloc((e->numberOfOperands() - numberOfChildren) * sizeof(Expression*));
int j = 0;
for (int i(0); i<e->numberOfOperands(); i++) {
// if the expression was not matched, give it to the wildcard.
if (selectorMatched[i] == kUnmatched) {
local_expr[j++] = e->operand(i);
}
}
matches[offset + numberOfMatches++] = ExpressionMatch(local_expr, j);
free(local_expr);
}
free(selectorMatched);
return numberOfMatches;
}
/* This helper function finds whether there is a commutative match or not.
* The output is the selector matched for each expression, written in the
* selectorMatched table.
* The matches table will be written to, but will not overwrite any previous
* data so this is ok.
* leftToMatch tells it how many selectors still have to be matched.
* Implementation detail: selectors are matched in ascending order.
*/
bool ExpressionSelector::canCommutativelyMatch(const Expression * e,
ExpressionMatch * matches,
uint8_t * selectorMatched,
int leftToMatch,
int offset) {
bool hasWildcard = child(m_numberOfChildren-1)->m_match == ExpressionSelector::Match::Wildcard;
// This part is used to make sure that we stop once we matched everything.
if (leftToMatch == 0) {
if (hasWildcard) {
return true;
} else {
/* We check that we matched all the children expressions.
* This can happen if the selector does not have a wildcard and we matched all
* the selectors, but there are still unmatched children expression.
* An example is the expression:
* +
* / | \
* 1 2 3
* Which would otherwise be matched by
* +
* / \
* / \
* Int Int
*/
int matchedChildren = 0;
for (int i = 0; i<e->numberOfOperands(); i++) {
if (selectorMatched[i] != kUnmatched) {
matchedChildren++;
}
}
if (matchedChildren == e->numberOfOperands()) {
return true;
} else {
return false;
}
}
}
// We try to match the i-th child selector.
int i = numberOfNonWildcardChildren() - leftToMatch;
for (int j = 0; j<e->numberOfOperands(); j++) {
// If the child has already been matched, we skip it.
if (selectorMatched[j] != kUnmatched) {
continue;
}
int numberOfMatches = child(i)->match(e->operand(j), matches, offset);
if (numberOfMatches) {
// We managed to match this selector.
selectorMatched[j] = i;
/* We check that we can match the rest in this configuration, if so we
* are good. */
if (this->canCommutativelyMatch(e, matches, selectorMatched, leftToMatch - 1, offset + numberOfMatches)) {
return true;
}
// Otherwise we backtrack.
selectorMatched[j] = kUnmatched;
}
}
return false;
}
/* Extrude in a class impossible otherwise ExpressionBuilder is not aggregate
* and cannot be initialized statically. */
ExpressionSelector * ExpressionSelector::child(int index) {
assert(index>=0 && index<m_numberOfChildren);
if (index == 0) {
return (this+1); // Pointer arithmetics
} else {
ExpressionSelector * previousChild = this->child(index-1);
return previousChild+previousChild->m_numberOfChildren+1; // Pointer arithm.
}
}
}

View File

@@ -1,16 +0,0 @@
#ifndef POINCARE_SIMPLIFY_MERGE_ADDITION_H
#define POINCARE_SIMPLIFY_MERGE_ADDITION_H
#include "transform.h"
namespace Poincare {
class MergeAddition : public Transform {
public:
constexpr MergeAddition() {};
void apply(Expression * root, Expression * captures[]) const override;
};
}
#endif

View File

@@ -1,24 +0,0 @@
#ifndef POINCARE_SIMPLIFY_SAME_AS_SELECTOR_H
#define POINCARE_SIMPLIFY_SAME_AS_SELECTOR_H
#include "selector.h"
namespace Poincare {
class SameAsSelector : public Selector {
public:
constexpr SameAsSelector(int originalIndex, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0);
bool acceptsLocationInCombination(const Combination * combination, int location) const override;
private:
int m_originalIndex;
};
constexpr SameAsSelector::SameAsSelector(int originalIndex, int captureIndex, Selector ** children, int numberOfChildren) :
Selector(captureIndex, children, numberOfChildren),
m_originalIndex(originalIndex)
{
}
}
#endif

View File

@@ -1,14 +0,0 @@
#include "simplification.h"
namespace Poincare {
Expression * Simplification::simplify(Expression * expression) const {
ExpressionMatch matches[255]; // FIXME: The size ca be given by our compiler
if (m_selector->match(expression, matches)) {
return m_builder->build(matches);
} else {
return nullptr;
}
}
}

View File

@@ -1,29 +0,0 @@
#ifndef POINCARE_SIMPLIFY_SIMPLIFICATION_H
#define POINCARE_SIMPLIFY_SIMPLIFICATION_H
#include <poincare/expression.h>
#include "expression_selector.h"
#include "expression_builder.h"
namespace Poincare {
class Simplification {
public:
constexpr Simplification(ExpressionSelector * m_selector, ExpressionBuilder * m_builder);
Expression * simplify(Expression * expression) const;
private:
ExpressionSelector * m_selector;
ExpressionBuilder * m_builder;
};
constexpr Simplification::Simplification(
ExpressionSelector * selector,
ExpressionBuilder * builder)
:
m_selector(selector),
m_builder(builder) {
}
}
#endif

View File

@@ -1,33 +0,0 @@
#include "simplification_generator.h"
#include <poincare/integer.h>
extern "C" {
#include <assert.h>
}
namespace Poincare {
Expression * SimplificationGenerator::AddIntegers(Expression ** parameters, int numberOfParameters) {
Integer * result = new Integer((native_int_t)0);
for (int i=0; i<numberOfParameters; i++) {
assert(parameters[i]->type() == Expression::Type::Integer);
*result = result->add(*(Integer *)parameters[i]);
/* Note We have to delete the parameters as they have been cloned before and
* we are the last ones to use them here. */
delete parameters[i];
}
return result;
}
Expression * SimplificationGenerator::MultiplyIntegers(Expression ** parameters, int numberOfParameters) {
Integer * result = new Integer((native_int_t)1);
for (int i=0; i<numberOfParameters; i++) {
assert(parameters[i]->type() == Expression::Type::Integer);
*result = result->multiply_by(*(Integer *)parameters[i]);
/* Note We have to delete the parameters as they have been cloned before and
* we are the last ones to use them here. */
delete parameters[i];
}
return result;
}
}

View File

@@ -1,16 +0,0 @@
#ifndef POINCARE_SIMPLIFY_SIMPLIFICATION_GENERATOR_H
#define POINCARE_SIMPLIFY_SIMPLIFICATION_GENERATOR_H
#include <poincare/expression.h>
namespace Poincare {
class SimplificationGenerator {
public:
static Expression * AddIntegers(Expression ** parameters, int numberOfParameters);
static Expression * MultiplyIntegers(Expression ** parameters, int numberOfParameters);
};
}
#endif

View File

@@ -1,26 +0,0 @@
#ifndef POINCARE_SIMPLIFY_TYPE_AND_VALUE_SELECTOR_H
#define POINCARE_SIMPLIFY_TYPE_AND_VALUE_SELECTOR_H
#include "selector.h"
namespace Poincare {
class TypeAndValueSelector : public Selector {
public:
constexpr TypeAndValueSelector(Expression::Type type, int value, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0);
bool acceptsLocationInCombination(const Combination * combination, int location) const override;
private:
Expression::Type m_type;
int m_value;
};
constexpr TypeAndValueSelector::TypeAndValueSelector(Expression::Type type, int value, int captureIndex, Selector ** children, int numberOfChildren) :
Selector(captureIndex, children, numberOfChildren),
m_type(type),
m_value(value)
{
}
}
#endif