First version of the simplifications.

Change-Id: Idbddb92b6bd098d6b862f5fc4abd741948e15194
This commit is contained in:
Felix Raimundo
2016-04-01 10:40:54 +02:00
parent 6232079f02
commit ed2c4cfb59
37 changed files with 460 additions and 149 deletions

View File

@@ -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\

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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;
}

View File

@@ -19,3 +19,10 @@ Expression::Type Product::type() {
char Product::operatorChar() {
return '*';
}
#ifdef DEBUG
int Product::getPrintableVersion(char* txt) {
txt[0] = '*';
return 1;
}
#endif

View File

@@ -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;

View File

@@ -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;

View 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;
}

View 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

View File

@@ -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;
}
}
}

View File

@@ -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 {

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
//}
}

View File

@@ -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");
}