Skip to content

Instantly share code, notes, and snippets.

(print-expr expr)
=> "(+ 1 2 (* 0 x y) (* 1 y 2) (+ 0 x))"
(print-expr (optimize expr))
=> "(+ 3 (* 2 y) x)"
(print-expr expr)
=> "(+ 1 2 (* 0 x y) (* 1 y 2) (+ 0 x))"
(print-expr (partial-eval {"y" 0} expr))
=> "(+ 3 x)"
(print-expr (optimize expr))
=> "(+ 3 (* 2 y) x)"
(evaluate {"x" 1 "y" 2} expr)
=> 8
(partial-eval {"x" 1 "y" 2} expr)
=> 8
#include <boost/algorithm/string/join.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/numeric.hpp>
#include <boost/variant.hpp>
using nb = int;
using id = std::string;
struct add_tag {};
struct mul_tag {};
template<typename Tag, typename R>
struct op
{
op() = default;
expression cst(int i) { return expression(i); };
expression var(id id) { return expression(id); };
expression add(std::vector<expression> const& rands)
{
return expression(add_op<expression>{ rands });
}
expression mul(std::vector<expression> const& rands)
expression e = add({
cst(1),
cst(2),
mul({cst(0), var("x"), var("y")}),
mul({cst(1), var("y"), cst(2)}),
add({cst(0), var("x")})
});
template <typename T>
int const* get_as_cst(expression_r<T> const& e)
{
return boost::get<int>(&e);
}
template <typename T>
id const* get_as_var(expression_r<T> const& e)
{
return boost::get<id>(&e);
struct expression
: boost::recursive_wrapper<expression_r<expression>>
{
using boost::recursive_wrapper<expression_r<expression>>::recursive_wrapper;
};
template<typename A, typename M>
auto fmap(M map, expression_r<A> const& e)
{
using B = decltype(map(std::declval<A>()));
using Out = expression_r<B>;
if (auto* o = get_as_add(e))
return Out(add_op<B>(o->rands() | transformed(map)));
if (auto* o = get_as_mul(e))