mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-19 13:50:28 +01:00
First version of the simplifications.
Change-Id: Idbddb92b6bd098d6b862f5fc4abd741948e15194
This commit is contained in:
@@ -28,8 +28,9 @@ objs += $(addprefix poincare/src/layout/,\
|
||||
string_layout.o\
|
||||
)
|
||||
objs += $(addprefix poincare/src/simplify/,\
|
||||
expression_selector.o\
|
||||
expression_builder.o\
|
||||
expression_match.o\
|
||||
expression_selector.o\
|
||||
simplification.o\
|
||||
simplification_generator.o\
|
||||
simplification_rules.o\
|
||||
|
||||
@@ -9,6 +9,9 @@ class Addition : public CommutativeOperation {
|
||||
Type type() override;
|
||||
float operateApproximatevelyOn(float a, float b) override;
|
||||
Expression * clone() override;
|
||||
#ifdef DEBUG
|
||||
int getPrintableVersion(char* txt) override;
|
||||
#endif
|
||||
protected:
|
||||
char operatorChar() override;
|
||||
};
|
||||
|
||||
@@ -9,6 +9,9 @@ class Cosine : public Function {
|
||||
float approximate(Context& context) override;
|
||||
Type type() override;
|
||||
Expression * clone() override;
|
||||
#ifdef DEBUG
|
||||
int getPrintableVersion(char* txt) override;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
#include <poincare/expression_layout.h>
|
||||
#include <kandinsky.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define PRINT_AST(e) e->__printAst(0)
|
||||
#else
|
||||
#define PRINT_AST(e) ((void)0)
|
||||
#endif
|
||||
|
||||
class Context;
|
||||
|
||||
class Expression {
|
||||
@@ -12,8 +18,8 @@ class Expression {
|
||||
Addition,
|
||||
Cosine,
|
||||
Float,
|
||||
Fraction,
|
||||
Integer,
|
||||
Fraction,
|
||||
Power,
|
||||
Product,
|
||||
Sine,
|
||||
@@ -45,6 +51,10 @@ class Expression {
|
||||
/*private:
|
||||
void forEachChild(ExpressionAction);
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
virtual int getPrintableVersion(char* txt) = 0;
|
||||
void __printAst(int level=0);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,9 @@ class Float : public LeafExpression {
|
||||
Type type() override;
|
||||
Expression * clone() override;
|
||||
bool valueEquals(Expression * e) override;
|
||||
#ifdef DEBUG
|
||||
int getPrintableVersion(char* txt) override;
|
||||
#endif
|
||||
private:
|
||||
float m_float;
|
||||
};
|
||||
|
||||
@@ -10,6 +10,9 @@ class Fraction : public BinaryOperation {
|
||||
float approximate(Context& context) override;
|
||||
Type type() override;
|
||||
Expression * clone() override;
|
||||
#ifdef DEBUG
|
||||
int getPrintableVersion(char* txt) override;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -45,6 +45,10 @@ class Integer : public LeafExpression {
|
||||
native_uint_t * m_digits; // LITTLE-ENDIAN
|
||||
uint16_t m_numberOfDigits; // In base native_uint_max
|
||||
bool m_negative;
|
||||
|
||||
#ifdef DEBUG
|
||||
int getPrintableVersion(char* txt) override;
|
||||
#endif
|
||||
/*
|
||||
// TODO: Small-int optimization
|
||||
union {
|
||||
|
||||
@@ -10,6 +10,9 @@ class Power : public BinaryOperation {
|
||||
float approximate(Context& context) override;
|
||||
Type type() override;
|
||||
Expression * clone() override;
|
||||
#ifdef DEBUG
|
||||
int getPrintableVersion(char* txt) override;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,9 @@ class Product : public CommutativeOperation {
|
||||
Type type() override;
|
||||
float operateApproximatevelyOn(float a, float b) override;
|
||||
Expression * clone() override;
|
||||
#ifdef DEBUG
|
||||
int getPrintableVersion(char* txt) override;
|
||||
#endif
|
||||
protected:
|
||||
char operatorChar() override;
|
||||
};
|
||||
|
||||
@@ -9,6 +9,9 @@ class Sine : public Function {
|
||||
float approximate(Context& context) override;
|
||||
Type type() override;
|
||||
Expression * clone() override;
|
||||
#ifdef DEBUG
|
||||
int getPrintableVersion(char* txt) override;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,9 @@ class Subtraction : public BinaryOperation {
|
||||
float approximate(Context& context) override;
|
||||
Type type() override;
|
||||
Expression * clone() override;
|
||||
#ifdef DEBUG
|
||||
int getPrintableVersion(char* txt) override;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,9 @@ class Symbol : public LeafExpression {
|
||||
Type type() override;
|
||||
Expression * clone() override;
|
||||
bool valueEquals(Expression * e) override;
|
||||
#ifdef DEBUG
|
||||
int getPrintableVersion(char* txt) override;
|
||||
#endif
|
||||
private:
|
||||
char * m_name;
|
||||
};
|
||||
|
||||
@@ -9,6 +9,9 @@ class Tangent : public Function {
|
||||
float approximate(Context& context) override;
|
||||
Type type() override;
|
||||
Expression * clone() override;
|
||||
#ifdef DEBUG
|
||||
int getPrintableVersion(char* txt) override;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,3 +16,10 @@ float Addition::operateApproximatevelyOn(float a, float b) {
|
||||
char Addition::operatorChar() {
|
||||
return '+';
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int Addition::getPrintableVersion(char* txt) {
|
||||
txt[0] = '+';
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -13,3 +13,13 @@ float Cosine::approximate(Context& context) {
|
||||
// FIXME: use cosine obviously.
|
||||
return m_arg->approximate(context);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int Cosine::getPrintableVersion(char* txt) {
|
||||
const char* printable = "cos";
|
||||
for(int i=0; printable[i]!='\0'; i++) {
|
||||
txt[i] = printable[i];
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -7,6 +7,11 @@ extern "C" {
|
||||
|
||||
#include "simplify/simplification_rules.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
#endif
|
||||
|
||||
int poincare_expression_yyparse(yyscan_t scanner, Expression ** expressionOutput);
|
||||
|
||||
Expression::~Expression() {
|
||||
@@ -33,6 +38,8 @@ Expression * Expression::simplify() {
|
||||
const Simplification * simplification = (simplifications + i); // Pointer arithmetics
|
||||
Expression * simplified = simplification->simplify(result);
|
||||
if (simplified != nullptr) {
|
||||
std::cout << "simplification " << i << " returned a non null pointer" << std::endl;
|
||||
PRINT_AST(simplified);
|
||||
simplification_pass_was_useful = true;
|
||||
if (result != this) {
|
||||
delete result;
|
||||
@@ -63,3 +70,18 @@ bool Expression::valueEquals(Expression * e) {
|
||||
* -riden. */
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void Expression::__printAst(int level) {
|
||||
char txt[255];
|
||||
for (int i(0); i<level; i++) {
|
||||
txt[i] = ' ';
|
||||
}
|
||||
int offset = getPrintableVersion(&txt[level]);
|
||||
txt[level + offset] = '\0';
|
||||
std::cout << txt << std::endl;
|
||||
for (int i(0); i < numberOfOperands(); i++) {
|
||||
operand(i)->__printAst(level + 2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include <poincare/float.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
}
|
||||
|
||||
#include <poincare/float.h>
|
||||
|
||||
Float::Float(float f) : m_float(f) {
|
||||
}
|
||||
|
||||
@@ -30,3 +33,13 @@ bool Float::valueEquals(Expression * e) {
|
||||
assert(e->type() == Expression::Type::Float);
|
||||
return m_float == ((Float *)e)->m_float;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int Float::getPrintableVersion(char* txt) {
|
||||
const char* printable = "float number";
|
||||
for(int i=0; printable[i]!='\0'; i++) {
|
||||
txt[i] = printable[i];
|
||||
}
|
||||
return strlen(printable);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -18,3 +18,10 @@ float Fraction::approximate(Context& context) {
|
||||
Expression::Type Fraction::type() {
|
||||
return Expression::Type::Fraction;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int Fraction::getPrintableVersion(char* txt) {
|
||||
txt[0] = '/';
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -344,6 +344,30 @@ ExpressionLayout * Integer::createLayout() {
|
||||
return new StringLayout(buffer, size);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int Integer::getPrintableVersion(char* txt) {
|
||||
Integer base = Integer(10);
|
||||
Division d = Division(*this, base);
|
||||
int size = 0;
|
||||
while (!(d.m_remainder == Integer((native_int_t)0))) {
|
||||
assert(size<255); //TODO: malloc an extra buffer
|
||||
char c = char_from_digit(d.m_remainder.m_digits[0]);
|
||||
txt[size++] = c;
|
||||
d = Division(d.m_quotient, base);
|
||||
}
|
||||
txt[size] = 0;
|
||||
|
||||
// Flip the string
|
||||
for (int i=0, j=size-1 ; i < j ; i++, j--) {
|
||||
char c = txt[i];
|
||||
txt[i] = txt[j];
|
||||
txt[j] = c;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Integer::valueEquals(Expression * e) {
|
||||
assert(e->type() == Expression::Type::Integer);
|
||||
return (*this == *(Integer *)e); // FIXME: Remove operator overloading
|
||||
|
||||
@@ -17,3 +17,10 @@ Expression::Type Power::type() {
|
||||
ExpressionLayout * Power::createLayout() {
|
||||
return new ExponentLayout(m_operands[0]->createLayout(), m_operands[1]->createLayout());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int Power::getPrintableVersion(char* txt) {
|
||||
txt[0] = '^';
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
19
poincare/src/print_ast.cpp
Normal file
19
poincare/src/print_ast.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <poincare/integer.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
int __print_ast(Expression* expression, int offset) {
|
||||
// TODO print my current node.
|
||||
char txt[offset+1] = {' '};
|
||||
text[offset] = '\0';
|
||||
cout << txt;
|
||||
|
||||
// Print my children.
|
||||
for (int i(0); i<expression->m_operands(); i++) {
|
||||
int tmp = __print_ast(expression->operand(i), offset);
|
||||
offset += tmp;
|
||||
}
|
||||
|
||||
return 3;
|
||||
}
|
||||
@@ -19,3 +19,10 @@ Expression::Type Product::type() {
|
||||
char Product::operatorChar() {
|
||||
return '*';
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int Product::getPrintableVersion(char* txt) {
|
||||
txt[0] = '*';
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,34 +1,39 @@
|
||||
#include "expression_builder.h"
|
||||
#include <poincare/addition.h>
|
||||
#include <poincare/integer.h>
|
||||
#include <poincare/product.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
}
|
||||
|
||||
/* Our compiler defines two things:
|
||||
* - First, a list of ExpressionBuilder
|
||||
* - Second, a children_expression_buffer[] of the proper size.
|
||||
*/
|
||||
|
||||
Expression * children_expression_buffer[4]; // This will be defined by our compiler
|
||||
|
||||
Expression * ExpressionBuilder::build(Expression * matches[]) {
|
||||
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)
|
||||
// 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);
|
||||
children_expressions[i] = child->build(matches);
|
||||
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::BuildFromTypeAndValue:
|
||||
switch(m_expressionType) {
|
||||
case Expression::Type::Addition:
|
||||
result = new Addition(children_expressions, m_numberOfChildren, true);
|
||||
result = new Addition(children_expressions, numberOfChildrenExpressions, true);
|
||||
break;
|
||||
case Expression::Type::Product:
|
||||
result = new Product(children_expressions, numberOfChildrenExpressions, true);
|
||||
break;
|
||||
case Expression::Type::Integer:
|
||||
result = new Integer(m_integerValue);
|
||||
@@ -38,11 +43,17 @@ Expression * ExpressionBuilder::build(Expression * matches[]) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ExpressionBuilder::Action::BringUpWildcard:
|
||||
// Build should never be called on BringUpWildcard action directly
|
||||
assert(false);
|
||||
break;
|
||||
case ExpressionBuilder::Action::Clone:
|
||||
result = matches[m_matchIndex]->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, m_numberOfChildren);
|
||||
result = m_generator(children_expressions, numberOfChildrenExpressions);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define POINCARE_SIMPLIFY_EXPRESSION_BUILDER_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
#include "expression_match.h"
|
||||
extern "C" {
|
||||
#include <stdint.h>
|
||||
}
|
||||
@@ -11,11 +12,12 @@ class ExpressionBuilder {
|
||||
typedef Expression * (ExternalGenerator)(Expression ** parameters, int numberOfParameters);
|
||||
public:
|
||||
ExpressionBuilder * child(int i);
|
||||
Expression * build(Expression * matches[]);
|
||||
Expression * build(ExpressionMatch matches[]);
|
||||
|
||||
enum class Action {
|
||||
BuildFromTypeAndValue,
|
||||
Clone,
|
||||
BringUpWildcard,
|
||||
CallExternalGenerator
|
||||
};
|
||||
|
||||
@@ -32,7 +34,7 @@ public:
|
||||
char const * m_symbolName;
|
||||
};
|
||||
};
|
||||
// m_action == Clone
|
||||
// m_action == Clone or BringUpWildcard
|
||||
uint8_t m_matchIndex;
|
||||
// m_action == CallExternalGenerator
|
||||
ExternalGenerator * m_generator;
|
||||
|
||||
44
poincare/src/simplify/expression_match.cpp
Normal file
44
poincare/src/simplify/expression_match.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "expression_match.h"
|
||||
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
ExpressionMatch::ExpressionMatch() {
|
||||
m_numberOfExpressions = 0;
|
||||
m_expressions = nullptr;
|
||||
}
|
||||
|
||||
ExpressionMatch::ExpressionMatch(Expression ** expressions, int numberOfExpressions) {
|
||||
m_numberOfExpressions = numberOfExpressions;
|
||||
m_expressions = (Expression**) malloc(m_numberOfExpressions * sizeof(ExpressionMatch*));
|
||||
for (int i(0); i<numberOfExpressions; i++) {
|
||||
m_expressions[i] = expressions[i];
|
||||
}
|
||||
}
|
||||
|
||||
ExpressionMatch::~ExpressionMatch() {
|
||||
if (m_numberOfExpressions != 0) {
|
||||
free(m_expressions);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
other.m_numberOfExpressions = 0; // Here we make sure that the memory containing the expressions is not freed.
|
||||
m_expressions = other.m_expressions;
|
||||
return *this;
|
||||
}
|
||||
22
poincare/src/simplify/expression_match.h
Normal file
22
poincare/src/simplify/expression_match.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef POINCARE_SIMPLIFY_EXPRESSION_MATCH_H
|
||||
#define POINCARE_SIMPLIFY_EXPRESSION_MATCH_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
extern "C" {
|
||||
#include <stdint.h>
|
||||
}
|
||||
|
||||
class ExpressionMatch {
|
||||
public:
|
||||
ExpressionMatch();
|
||||
ExpressionMatch(Expression ** expressions, int numberOfExpressions);
|
||||
~ExpressionMatch();
|
||||
Expression * expression(int i);
|
||||
int numberOfExpressions();
|
||||
ExpressionMatch& operator=(ExpressionMatch&& other);
|
||||
private:
|
||||
Expression ** m_expressions;
|
||||
int m_numberOfExpressions;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -3,7 +3,7 @@ extern "C" {
|
||||
#include <assert.h>
|
||||
}
|
||||
|
||||
int ExpressionSelector::match(Expression * e, ExpressionMatch ** matches) {
|
||||
int ExpressionSelector::match(Expression * e, ExpressionMatch * matches) {
|
||||
int numberOfMatches = 0;
|
||||
|
||||
// Does the current node match?
|
||||
@@ -11,7 +11,7 @@ int ExpressionSelector::match(Expression * e, ExpressionMatch ** matches) {
|
||||
case ExpressionSelector::Match::Any:
|
||||
// Yes, it always does!
|
||||
break;
|
||||
case ExpressionSelector::Match::TypeAndValue:
|
||||
case ExpressionSelector::Match::Type:
|
||||
if (e->type() != m_expressionType) {
|
||||
return 0;
|
||||
}
|
||||
@@ -23,32 +23,26 @@ int ExpressionSelector::match(Expression * e, ExpressionMatch ** matches) {
|
||||
}
|
||||
|
||||
// The current node does match. Let's add it to our matches
|
||||
// FIXME
|
||||
matches[numberOfMatches++] = ExpressionMatch(&e, 1);
|
||||
//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);
|
||||
|
||||
if (childSelector->m_match == ExpressionSelector::Match::WildCard) {
|
||||
assert(i == m_numberOfChildren-1); // Wildcards should be the last argument!
|
||||
Expression * pouet[255];//TODO
|
||||
for (int j=i; j<childSelector->numberOfOperands(); j++) {
|
||||
pouet[j-i] = e->operand(j);
|
||||
ExpressionMatch(e->operand(j...));
|
||||
Expression * local_expr[255];
|
||||
for (int j=i; j<e->numberOfOperands(); j++) {
|
||||
local_expr[j-i] = e->operand(j);
|
||||
}
|
||||
matches[i+1] = ExpressionMatch(pouet, childSelector->numberOfOperands() - i +1);
|
||||
}
|
||||
int numberOfChildMatches = childSelector->match(childExpression, (matches+numberOfMatches));
|
||||
if (numberOfChildMatches == 0) {
|
||||
return 0;
|
||||
matches[numberOfMatches++] = ExpressionMatch(local_expr, e->numberOfOperands() - i);
|
||||
} else {
|
||||
numberOfMatches += numberOfChildMatches;
|
||||
int numberOfChildMatches = childSelector->match(childExpression, (matches+numberOfMatches));
|
||||
if (numberOfChildMatches == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
numberOfMatches += numberOfChildMatches;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class ExpressionSelector {
|
||||
public:
|
||||
enum class Match {
|
||||
Any,
|
||||
TypeAndValue,
|
||||
Type,
|
||||
WildCard,
|
||||
};
|
||||
ExpressionSelector * child(int i);
|
||||
@@ -23,7 +23,7 @@ public:
|
||||
* Caution: This function *will* write to *matches even if the returned
|
||||
* value is zero.
|
||||
*/
|
||||
int match(Expression * e, ExpressionMatch ** matches);
|
||||
int match(Expression * e, ExpressionMatch * matches);
|
||||
|
||||
Match m_match;
|
||||
union {
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
#include "simplification.h"
|
||||
|
||||
Expression * Simplification::simplify(Expression * expression) const {
|
||||
ExpressionMatch * matches[255]; // FIXME: The size ca be given by our compiler
|
||||
ExpressionMatch matches[255]; // FIXME: The size ca be given by our compiler
|
||||
if (m_selector->match(expression, matches)) {
|
||||
if (expression->numberOfOperands() == m_selector->m_numberOfChildren) {
|
||||
return m_builder->build(matches);
|
||||
}
|
||||
return m_builder->build(matches);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ Expression * SimplificationGenerator::AddIntegers(Expression ** parameters, int
|
||||
assert(parameters[i]->type() == Expression::Type::Integer);
|
||||
// FIXME: get rid of this operator overloading.
|
||||
*result = *result + *(Integer *)parameters[i];
|
||||
delete paramett[i]
|
||||
delete parameters[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,67 +1,98 @@
|
||||
#include "simplification_rules.h"
|
||||
#include "simplification_generator.h"
|
||||
|
||||
const ExpressionSelector additionCommutativeSelector[5] = {
|
||||
const ExpressionSelector additionCommutativeWCSelector[4] = {
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::TypeAndValue,
|
||||
.m_match = ExpressionSelector::Match::Type,
|
||||
.m_expressionType = Expression::Type::Addition,
|
||||
.m_numberOfChildren = 2
|
||||
},
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::Any,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::TypeAndValue,
|
||||
.m_match = ExpressionSelector::Match::Type,
|
||||
.m_expressionType = Expression::Type::Addition,
|
||||
.m_numberOfChildren = 2,
|
||||
.m_numberOfChildren = 1,
|
||||
},
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::Any,
|
||||
.m_match = ExpressionSelector::Match::WildCard,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::Any,
|
||||
.m_match = ExpressionSelector::Match::WildCard,
|
||||
.m_numberOfChildren = 0
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const ExpressionBuilder additionCommutativeBuilder[4] = {
|
||||
const ExpressionBuilder additionCommutativeWCBuilder[3] = {
|
||||
{
|
||||
.m_action = ExpressionBuilder::Action::BuildFromTypeAndValue,
|
||||
.m_expressionType = Expression::Type::Addition,
|
||||
.m_numberOfChildren = 3
|
||||
.m_numberOfChildren = 2
|
||||
},
|
||||
{
|
||||
.m_action = ExpressionBuilder::Action::Clone,
|
||||
.m_matchIndex = 1,
|
||||
.m_action = ExpressionBuilder::Action::BringUpWildcard,
|
||||
.m_matchIndex = 2,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
{
|
||||
.m_action = ExpressionBuilder::Action::Clone,
|
||||
.m_action = ExpressionBuilder::Action::BringUpWildcard,
|
||||
.m_matchIndex = 3,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
{
|
||||
.m_action = ExpressionBuilder::Action::Clone,
|
||||
.m_matchIndex = 4,
|
||||
.m_numberOfChildren = 0
|
||||
}
|
||||
};
|
||||
|
||||
const ExpressionSelector multiplyCommutativeWCSelector[4] = {
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::Type,
|
||||
.m_expressionType = Expression::Type::Product,
|
||||
.m_numberOfChildren = 2
|
||||
},
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::Type,
|
||||
.m_expressionType = Expression::Type::Product,
|
||||
.m_numberOfChildren = 1,
|
||||
},
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::WildCard,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::WildCard,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
};
|
||||
|
||||
const ExpressionBuilder multiplyCommutativeWCBuilder[3] = {
|
||||
{
|
||||
.m_action = ExpressionBuilder::Action::BuildFromTypeAndValue,
|
||||
.m_expressionType = Expression::Type::Product,
|
||||
.m_numberOfChildren = 2
|
||||
},
|
||||
{
|
||||
.m_action = ExpressionBuilder::Action::BringUpWildcard,
|
||||
.m_matchIndex = 2,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
{
|
||||
.m_action = ExpressionBuilder::Action::BringUpWildcard,
|
||||
.m_matchIndex = 3,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
const ExpressionSelector additionIntegerSelector[3] = {
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::TypeAndValue,
|
||||
.m_match = ExpressionSelector::Match::Type,
|
||||
.m_expressionType = Expression::Type::Addition,
|
||||
.m_numberOfChildren = 2
|
||||
},
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::TypeAndValue,
|
||||
.m_match = ExpressionSelector::Match::Type,
|
||||
.m_expressionType = Expression::Type::Integer,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::TypeAndValue,
|
||||
.m_match = ExpressionSelector::Match::Type,
|
||||
.m_expressionType = Expression::Type::Integer,
|
||||
.m_numberOfChildren = 0
|
||||
}
|
||||
@@ -85,15 +116,73 @@ const ExpressionBuilder additionIntegerBuilder[3] = {
|
||||
}
|
||||
};
|
||||
|
||||
const Simplification simplifications[2] = {
|
||||
const ExpressionSelector additionIntegerWCSelector[4] = {
|
||||
{
|
||||
.m_selector = (ExpressionSelector *)additionCommutativeSelector,
|
||||
.m_builder = (ExpressionBuilder *)additionCommutativeBuilder
|
||||
.m_match = ExpressionSelector::Match::Type,
|
||||
.m_expressionType = Expression::Type::Addition,
|
||||
.m_numberOfChildren = 3
|
||||
},
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::Type,
|
||||
.m_expressionType = Expression::Type::Integer,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::Type,
|
||||
.m_expressionType = Expression::Type::Integer,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
{
|
||||
.m_match = ExpressionSelector::Match::WildCard,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
};
|
||||
|
||||
const ExpressionBuilder additionIntegerWCBuilder[5] = {
|
||||
{
|
||||
.m_action = ExpressionBuilder::Action::BuildFromTypeAndValue,
|
||||
.m_expressionType = Expression::Type::Addition,
|
||||
.m_numberOfChildren = 2
|
||||
},
|
||||
{
|
||||
.m_action = ExpressionBuilder::Action::CallExternalGenerator,
|
||||
.m_generator = &SimplificationGenerator::AddIntegers,
|
||||
.m_numberOfChildren = 2
|
||||
},
|
||||
{
|
||||
.m_action = ExpressionBuilder::Action::Clone,
|
||||
.m_matchIndex = 1,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
{
|
||||
.m_action = ExpressionBuilder::Action::Clone,
|
||||
.m_matchIndex = 2,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
{
|
||||
.m_action = ExpressionBuilder::Action::BringUpWildcard,
|
||||
.m_matchIndex = 3,
|
||||
.m_numberOfChildren = 0
|
||||
},
|
||||
};
|
||||
|
||||
const Simplification simplifications[4] = {
|
||||
{
|
||||
.m_selector = (ExpressionSelector *)additionCommutativeWCSelector,
|
||||
.m_builder = (ExpressionBuilder *)additionCommutativeWCBuilder
|
||||
},
|
||||
{
|
||||
.m_selector = (ExpressionSelector *)multiplyCommutativeWCSelector,
|
||||
.m_builder = (ExpressionBuilder *)multiplyCommutativeWCBuilder
|
||||
},
|
||||
{
|
||||
.m_selector = (ExpressionSelector *)additionIntegerSelector,
|
||||
.m_builder = (ExpressionBuilder *)additionIntegerBuilder
|
||||
}
|
||||
},
|
||||
{
|
||||
.m_selector = (ExpressionSelector *)additionIntegerWCSelector,
|
||||
.m_builder = (ExpressionBuilder *)additionIntegerWCBuilder
|
||||
},
|
||||
};
|
||||
|
||||
const int knumberOfSimplifications = 2;
|
||||
const int knumberOfSimplifications = 4;
|
||||
|
||||
@@ -13,3 +13,13 @@ float Sine::approximate(Context& context) {
|
||||
// FIXME: use sine obviously.
|
||||
return m_arg->approximate(context);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int Sine::getPrintableVersion(char* txt) {
|
||||
const char* printable = "sin";
|
||||
for(int i=0; printable[i]!='\0'; i++) {
|
||||
txt[i] = printable[i];
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -25,3 +25,10 @@ ExpressionLayout * Subtraction::createLayout() {
|
||||
children_layouts[2] = m_operands[1]->createLayout();
|
||||
return new HorizontalLayout(children_layouts, 3);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int Subtraction::getPrintableVersion(char* txt) {
|
||||
txt[0] = '-';
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -38,3 +38,12 @@ bool Symbol::valueEquals(Expression * e) {
|
||||
assert(e->type() == Expression::Type::Symbol);
|
||||
return (strcmp(m_name, ((Symbol *)e)->m_name) == 0);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int Symbol::getPrintableVersion(char* txt) {
|
||||
for(int i=0; m_name[i]!='\0'; i++) {
|
||||
txt[i] = m_name[i];
|
||||
}
|
||||
return strlen(m_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -13,3 +13,13 @@ float Tangent::approximate(Context& context) {
|
||||
// FIXME: use tangent obviously.
|
||||
return m_arg->approximate(context);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int Tangent::getPrintableVersion(char* txt) {
|
||||
const char* printable = "tan";
|
||||
for(int i=0; printable[i]!='\0'; i++) {
|
||||
txt[i] = printable[i];
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
#include <assert.h>
|
||||
|
||||
QUIZ_CASE(poincare_simplify) {
|
||||
{
|
||||
Expression * e = Expression::parse("3*0");
|
||||
Expression * e2 = e->simplify();
|
||||
assert(e2->type() == Expression::Type::Integer);
|
||||
}
|
||||
{
|
||||
Expression * e = Expression::parse("0*foo");
|
||||
Expression * e2 = e->simplify();
|
||||
assert(e2->type() == Expression::Type::Integer);
|
||||
}
|
||||
//{
|
||||
// Expression * e = Expression::parse("3*0");
|
||||
// Expression * e2 = e->simplify();
|
||||
// assert(e2->type() == Expression::Type::Integer);
|
||||
//}
|
||||
//{
|
||||
// Expression * e = Expression::parse("0*foo");
|
||||
// Expression * e2 = e->simplify();
|
||||
// assert(e2->type() == Expression::Type::Integer);
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -1,89 +1,43 @@
|
||||
#include <quiz.h>
|
||||
#include <poincare.h>
|
||||
#include <assert.h>
|
||||
#if ULGY_DEBUG_HACK
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if ULGY_DEBUG_HACK
|
||||
void dump_ast(Expression * e, int level);
|
||||
#ifdef DEBUG
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
#endif
|
||||
|
||||
void assert_simplifies_to(const char * input_string, const char * expected_string) {
|
||||
//Expression* tab[3] = {new Integer(1), new Integer(2), new Integer(3)};
|
||||
//Expression* input = new Addition(tab, 3, false);
|
||||
Expression * input = Expression::parse(input_string);
|
||||
assert(input != nullptr);
|
||||
#if ULGY_DEBUG_HACK
|
||||
printf("Input = \n");
|
||||
dump_ast(input,0);
|
||||
#ifdef DEBUG
|
||||
cout << "Input = " << endl;
|
||||
PRINT_AST(input);
|
||||
#endif
|
||||
Expression * simplified = input->simplify();
|
||||
assert(simplified != nullptr);
|
||||
#if ULGY_DEBUG_HACK
|
||||
printf("Simplified = \n");
|
||||
dump_ast(simplified,0);
|
||||
#ifdef DEBUG
|
||||
cout << "Simplified = " << endl;
|
||||
PRINT_AST(simplified);
|
||||
#endif
|
||||
Expression * expected = Expression::parse(expected_string);
|
||||
assert(expected != nullptr);
|
||||
#if ULGY_DEBUG_HACK
|
||||
printf("Expected = \n");
|
||||
dump_ast(expected,0);
|
||||
#ifdef DEBUG
|
||||
cout << "Expected = " << endl;
|
||||
PRINT_AST(expected);
|
||||
#endif
|
||||
assert(simplified->isIdenticalTo(expected));
|
||||
delete expected;
|
||||
delete simplified;
|
||||
delete input;
|
||||
#if ULGY_DEBUG_HACK
|
||||
printf("----\n");
|
||||
#ifdef DEBUG
|
||||
cout << "----" << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ULGY_DEBUG_HACK
|
||||
void dump_ast(Expression * e, int level) {
|
||||
char expression_symbol;
|
||||
switch(e->type()) {
|
||||
case Expression::Type::Integer:
|
||||
expression_symbol = 'i';
|
||||
break;
|
||||
case Expression::Type::Addition:
|
||||
expression_symbol = '+';
|
||||
break;
|
||||
case Expression::Type::Power:
|
||||
expression_symbol = '^';
|
||||
break;
|
||||
case Expression::Type::Float:
|
||||
expression_symbol = 'f';
|
||||
break;
|
||||
case Expression::Type::Fraction:
|
||||
expression_symbol = '/';
|
||||
break;
|
||||
case Expression::Type::Product:
|
||||
expression_symbol = '*';
|
||||
break;
|
||||
case Expression::Type::Symbol:
|
||||
expression_symbol = 's';
|
||||
break;
|
||||
case Expression::Type::Subtraction:
|
||||
expression_symbol = '-';
|
||||
break;
|
||||
default:
|
||||
expression_symbol = '?';
|
||||
break;
|
||||
}
|
||||
char text[255];
|
||||
int cursor = 0;
|
||||
for (cursor=0; cursor<level; cursor++) {
|
||||
text[cursor] = ' ';
|
||||
}
|
||||
text[cursor++] = expression_symbol;
|
||||
text[cursor] = 0;
|
||||
printf("%s\n", text);
|
||||
for (int i=0; i<e->numberOfOperands(); i++) {
|
||||
dump_ast(e->operand(i), level+1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QUIZ_CASE(poincare_simplify_addition_integer) {
|
||||
//assert_simplifies_to("3+0", "3");
|
||||
//assert_simplifies_to("3+foo+2", "foo+5");
|
||||
//assert_simplifies_to("2+2", "4");
|
||||
assert_simplifies_to("2*2*2*2*2*2", "6");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user