Skip to content

Instantly share code, notes, and snippets.

@PhDP
Last active August 29, 2015 14:16
Show Gist options
  • Save PhDP/53fb0ff01af00aa26036 to your computer and use it in GitHub Desktop.
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...
#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