Poincare: Add an ExpressionSelector

Change-Id: I1ed0e2f3042f948d81d79b7b8ada00a3e838322b
This commit is contained in:
Romain Goyet
2016-03-26 18:46:27 +01:00
parent bdb4aaace3
commit f81239fdb8
3 changed files with 121 additions and 0 deletions

View File

@@ -32,6 +32,7 @@ objs += $(addprefix poincare/src/simplify/,\
simplify_addition_integer.o\
simplify_commutative_merge.o\
simplify_product_zero.o\
expression_selector.o\
)
tests += $(addprefix poincare/test/,\
addition.cpp\

View File

@@ -0,0 +1,67 @@
#include "expression_selector.h"
extern "C" {
#include <assert.h>
}
int ExpressionSelector::match(Expression * e, Expression ** matches) {
int numberOfMatches = 0;
// Does the current node match?
switch(m_match) {
case ExpressionSelector::Match::Any:
// Yes, it always does!
break;
case ExpressionSelector::Match::TypeAndValue:
if (e->type() != m_expressionType) {
return 0;
}
/*
switch (e->type()) {
case Expression::Type::Integer:
// Test e->equals(Integer(m_integerValue));
// Maybe return 0
break;
case Expression::Type::Symbol:
// Test symbol is same name
// Maybe return 0
break;
default:
// By default we don't check a value equality
}
*/
break;
}
// The current node does match. Let's add it to our matches
matches[numberOfMatches++] = e;
// FIXME: For now we'll ignore the commutativity of the Selector
// which is definitely something *very* important
// Checking if "e" is commutative seems like a nice solution
for (int i=0; i<m_numberOfChildren; i++) {
ExpressionSelector * childSelector = this->child(i);
// To account for commutativity, we should have multiple possibilities for childExpression
Expression * childExpression = e->operand(i);
int numberOfChildMatches = childSelector->match(childExpression, &matches[numberOfMatches]);
if (numberOfChildMatches == 0) {
return 0;
} else {
numberOfMatches += numberOfChildMatches;
}
}
return numberOfMatches;
}
// 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; // Pointer arithm.
}
}

View File

@@ -0,0 +1,53 @@
#ifndef POINCARE_SIMPLIFY_EXPRESSION_SELECTOR_H
#define POINCARE_SIMPLIFY_EXPRESSION_SELECTOR_H
#include <poincare/expression.h>
extern "C" {
#include <stdint.h>
}
class ExpressionSelector {
/* Everything must be made public otherwise we cannot static-initialize an
* array of ExpressionSelectors. */
public:
enum class Match {
Any,
TypeAndValue
};
ExpressionSelector * child(int i);
/* The match function is interesting
* - It returns 0 if the selector didn't match the expression
* - Otherwise, it returns the number of captured matches and sets *matches
* Caution: This function *will* write to *matches even if the returned
* value is zero.
*/
int match(Expression * e, Expression ** matches); // Return the matched expressions
/*Expression ** match(Expression * e);*/
Match m_match;
union {
// m_match == Any
// nothing!
// m_match == ExpressionType
struct {
Expression::Type m_expressionType;
union {
// m_expressionType == Integer
int32_t m_integerValue;
// m_expressionType == Symbol
char const * m_symbolName;
};
};
};
uint8_t m_numberOfChildren;
};
/*
{
my_tree_selector, my_expression_builder;
if (my_tree_selector->match(my_expression)) {
my_expression_builder->build(my_expression, *matchedData);
}
}
*/
#endif