[et] dsl
This commit is contained in:
		
							
								
								
									
										87
									
								
								examples/et/3_dsl.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								examples/et/3_dsl.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <tuple>
 | 
			
		||||
 | 
			
		||||
/* unchanged from et/2_generic_arity.cpp */
 | 
			
		||||
struct Add {
 | 
			
		||||
	template<typename T>
 | 
			
		||||
	static auto eval(T lhs, T rhs) {
 | 
			
		||||
		return lhs + rhs;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Mul {
 | 
			
		||||
	template<typename T>
 | 
			
		||||
	static auto eval(T lhs, T rhs) {
 | 
			
		||||
		return lhs * rhs;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
class Value {
 | 
			
		||||
	T _value;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	Value(T value): _value(value) {}
 | 
			
		||||
 | 
			
		||||
	auto eval() const { return _value; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename Op, typename... Operands>
 | 
			
		||||
class Expr {
 | 
			
		||||
	std::tuple<Operands...> _operands;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	Expr(Operands... operands): _operands{operands...} {}
 | 
			
		||||
 | 
			
		||||
	auto eval() const {
 | 
			
		||||
		return eval(std::make_index_sequence<sizeof...(Operands)>{});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	template<std::size_t... Is>
 | 
			
		||||
	auto eval(std::index_sequence<Is...>) const {
 | 
			
		||||
		return Op::eval(std::get<Is>(_operands).eval()...);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
/* end of unchanged */
 | 
			
		||||
 | 
			
		||||
namespace impl {
 | 
			
		||||
template<typename T> struct IsExpr: std::false_type {};
 | 
			
		||||
 | 
			
		||||
template<typename Op, typename... Operands>
 | 
			
		||||
struct IsExpr<Expr<Op, Operands...>>: std::true_type {};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
struct IsExpr<Value<T>>: std::true_type {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
constexpr bool IsExpr = impl::IsExpr<T>::value;
 | 
			
		||||
 | 
			
		||||
template<
 | 
			
		||||
	typename LHS, typename RHS,
 | 
			
		||||
	std::enable_if_t<IsExpr<LHS> && IsExpr<RHS>>* = nullptr
 | 
			
		||||
>
 | 
			
		||||
auto operator+(LHS lhs, RHS rhs) {
 | 
			
		||||
	return Expr<Add, LHS, RHS>{lhs, rhs};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<
 | 
			
		||||
	typename LHS, typename RHS,
 | 
			
		||||
	std::enable_if_t<IsExpr<LHS> && IsExpr<RHS>>* = nullptr
 | 
			
		||||
>
 | 
			
		||||
auto operator*(LHS lhs, RHS rhs) {
 | 
			
		||||
	return Expr<Mul, LHS, RHS>{lhs, rhs};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
	int volatile v[]{3, 5, 7};
 | 
			
		||||
	int result;
 | 
			
		||||
 | 
			
		||||
	Value<int> v0{v[0]}, v1{v[1]}, v2{v[2]};
 | 
			
		||||
 | 
			
		||||
	auto expr = v0 + v1 * v2;
 | 
			
		||||
	result = expr.eval();
 | 
			
		||||
 | 
			
		||||
	std::printf("%d\n", result);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user