Last active
August 29, 2015 14:16
-
-
Save PhDP/53fb0ff01af00aa26036 to your computer and use it in GitHub Desktop.
First example of Harrison's "Handbook of Practical Logic and Automated Reasoning" in C++11. Even clang-format couldn't improve this...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
#include <boost/variant.hpp> | |
struct Add; | |
struct Mult; | |
using Expr = boost::variant<int, std::string, boost::recursive_wrapper<Add>, | |
boost::recursive_wrapper<Mult>>; | |
struct Add { | |
Expr left, right; | |
Add(const Expr &lhs, const Expr &rhs) : left(lhs), right(rhs) { | |
} | |
}; | |
struct Mult { | |
Expr left, right; | |
Mult(const Expr &lhs, const Expr &rhs) : left(lhs), right(rhs) { | |
} | |
}; | |
struct add_visit : public boost::static_visitor<Expr> { | |
Expr operator()(int l, int r) const { | |
return Expr(l + r); | |
} | |
template <class X> Expr operator()(int l, const X &x) const { | |
if (l == 0) | |
return x; | |
return Add(Expr(l), Expr(x)); | |
} | |
template <class X> Expr operator()(const X &x, int r) const { | |
if (r == 0) | |
return x; | |
return Add(Expr(r), Expr(x)); | |
} | |
template <class X, class Y> Expr operator()(const X &x, const Y &y) const { | |
return Add(Expr(x), Expr(y)); | |
} | |
}; | |
struct mul_visit : public boost::static_visitor<Expr> { | |
Expr operator()(int l, int r) const { | |
return Expr(l * r); | |
} | |
template <class X> Expr operator()(int l, const X &x) const { | |
if (l == 0) | |
return Expr(0); | |
if (l == 1) | |
return x; | |
return Mult(Expr(l), Expr(x)); | |
} | |
template <class X> Expr operator()(const X &x, int r) const { | |
if (r == 0) | |
return Expr(0); | |
if (r == 1) | |
return x; | |
return Mult(Expr(r), Expr(x)); | |
} | |
template <class X, class Y> Expr operator()(const X &x, const Y &y) const { | |
return Mult(Expr(x), Expr(y)); | |
} | |
}; | |
struct simplify1 : public boost::static_visitor<Expr> { | |
Expr operator()(const Add &a) const { | |
return boost::apply_visitor(add_visit(), a.left, a.right); | |
} | |
Expr operator()(const Mult &m) const { | |
return boost::apply_visitor(mul_visit(), m.left, m.right); | |
} | |
template <class X> Expr operator()(const X &x) const { | |
return Expr(x); | |
} | |
}; | |
struct simplify : public boost::static_visitor<Expr> { | |
Expr operator()(const Add &a) const { | |
auto left = boost::apply_visitor(simplify(), a.left); | |
auto right = boost::apply_visitor(simplify(), a.right); | |
auto add_lr = boost::apply_visitor(add_visit(), left, right); | |
return boost::apply_visitor(simplify1(), add_lr); | |
} | |
Expr operator()(const Mult &m) const { | |
auto left = boost::apply_visitor(simplify(), m.left); | |
auto right = boost::apply_visitor(simplify(), m.right); | |
auto mul_lr = boost::apply_visitor(mul_visit(), left, right); | |
return boost::apply_visitor(simplify1(), mul_lr); | |
} | |
template <class X> Expr operator()(const X &x) const { | |
return x; | |
} | |
}; | |
auto main() -> int { | |
auto expr1 = Expr(Add( | |
Expr(Mult(Expr(Add(Expr(1), Expr(Mult(Expr(0), Expr("x"))))), Expr(3))), | |
Expr(12))); | |
auto ans = boost::apply_visitor(simplify(), expr1); | |
std::cout << boost::get<int>(ans) << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment