diff --git a/src/form/expression.cpp b/src/form/expression.cpp index 4966f354..a317c714 100644 --- a/src/form/expression.cpp +++ b/src/form/expression.cpp @@ -1,6 +1,7 @@ #include "form/expression.hpp" #include +#include #include Expression::Expression() @@ -202,6 +203,28 @@ void Expression::replaceName(const std::string& from, const std::string& to) { } } +void Expression::substituteFunction(const std::string& from, + const Expression& to, + const std::string& param) { + if (type == Type::FUNCTION && name == from) { + // sanity check + if (to.type != Type::FUNCTION || to.children.size() != 1) { + throw std::runtime_error("invalid function substitution: " + + to.toString()); + } + name = to.name; + Expression& arg = *children.front(); + Expression newArg = *to.children.front(); // copy + newArg.replaceAll(Expression(Type::PARAMETER, param), arg); + arg = newArg; + std::cout << "result " << toString() << std::endl; + return; + } + for (auto& c : children) { + c->substituteFunction(from, to, param); + } +} + std::ostream& operator<<(std::ostream& out, const Expression& e) { e.print(out, 0, true, Expression::Type::CONSTANT); return out; diff --git a/src/form/expression.hpp b/src/form/expression.hpp index af2865ec..2e92bb67 100644 --- a/src/form/expression.hpp +++ b/src/form/expression.hpp @@ -62,6 +62,9 @@ class Expression { void replaceName(const std::string& from, const std::string& to); + void substituteFunction(const std::string& from, const Expression& to, + const std::string& param); + friend std::ostream& operator<<(std::ostream& out, const Expression& e); std::string toString() const; diff --git a/src/form/formula.cpp b/src/form/formula.cpp index 8904781c..b89cde78 100644 --- a/src/form/formula.cpp +++ b/src/form/formula.cpp @@ -1,5 +1,6 @@ #include "form/formula.hpp" +#include #include #include "form/expression_util.hpp" @@ -138,6 +139,17 @@ void Formula::replaceName(const std::string& from, const std::string& to) { entries = newEntries; } +void Formula::substituteFunction(const std::string& from, + const Expression& to) { + const auto param = ExpressionUtil::newParameter(); + for (auto& e : entries) { + std::cout << "subst " << from << " -> " << to.toString() << " in " + << e.second.toString() << std::endl; + e.second.substituteFunction(from, to, param.name); + ExpressionUtil::normalize(e.second); + } +} + void Formula::collectEntries(const std::string& name, Formula& target) { for (auto& e : entries) { if (e.first.name == name) { @@ -159,14 +171,21 @@ void Formula::collectEntries(const Expression& e, Formula& target) { } } -void Formula::resolveIdentities() { +void Formula::resolveIdentities(const std::string& main) { auto copy = entries; for (auto& e : copy) { - if (ExpressionUtil::isSimpleFunction(e.first) && - ExpressionUtil::isSimpleFunction(e.second) && - copy.find(e.second) != copy.end()) { + if (!ExpressionUtil::isSimpleFunction(e.first, true) || + !ExpressionUtil::isSimpleFunction(e.second, false) || + e.first.name == main) { + continue; + } + auto r = ExpressionUtil::newFunction(e.second.name); + if (copy.find(r) != copy.end()) { + std::cout << "candidate " << e.first.toString() << " = " + << e.second.toString() << std::endl; entries.erase(e.first); - replaceName(e.second.name, e.first.name); + + substituteFunction(e.first.name, e.second); } } } diff --git a/src/form/formula.hpp b/src/form/formula.hpp index 41ca38b7..ac6f1112 100644 --- a/src/form/formula.hpp +++ b/src/form/formula.hpp @@ -24,11 +24,13 @@ class Formula { void replaceName(const std::string& from, const std::string& to); + void substituteFunction(const std::string& from, const Expression& to); + void collectEntries(const std::string& name, Formula& target); void collectEntries(const Expression& e, Formula& target); - void resolveIdentities(); + void resolveIdentities(const std::string& main); void resolveSimpleFunctions(); diff --git a/src/form/formula_gen.cpp b/src/form/formula_gen.cpp index 1b773558..5d3f6b6f 100644 --- a/src/form/formula_gen.cpp +++ b/src/form/formula_gen.cpp @@ -420,16 +420,16 @@ bool FormulaGenerator::generateSingle(const Program& p) { formula.resolveSimpleFunctions(); Log::get().debug("Resolved simple functions: " + formula.toString()); + // resolve identities + formula.resolveIdentities(getCellName(Program::OUTPUT_CELL)); + Log::get().debug("Resolved identities: " + formula.toString()); + // extract main formula (filter out irrelant memory cells) Formula tmp; formula.collectEntries(getCellName(Program::OUTPUT_CELL), tmp); formula = tmp; Log::get().debug("Pruned formula: " + formula.toString()); - // resolve identities - formula.resolveIdentities(); - Log::get().debug("Resolved identities: " + formula.toString()); - // success return true; }