Skip to content

Commit

Permalink
updated magical ExpressionBuilder (compile-time codegen)
Browse files Browse the repository at this point in the history
  • Loading branch information
MoeMod committed Jun 13, 2019
1 parent 2df9216 commit ddd49af
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 30 deletions.
77 changes: 50 additions & 27 deletions dlls/weapons/ExpressionBuilder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,26 @@ namespace ExpressionBuilder
const UnderlyingType c;
constexpr explicit ConstantType(UnderlyingType a) : c(a) {}
template<class T>
constexpr UnderlyingType operator()(T x) const
constexpr ConstantType<UnderlyingType> operator()(T x) const
{
return c;
return ConstantType<UnderlyingType>(c); // *this
}
constexpr operator UnderlyingType() const { return c; }
};

template<class T>
constexpr auto varcon(T x) -> typename std::enable_if<!IsExpression<T>::value, ConstantType<T>>::type
{
return ConstantType<T>(x);
}
template<class T>
constexpr auto varcon(T x) -> typename std::enable_if<IsExpression<T>::value, T>::type
{
return x;
}

template<class Varible, class Constant>
struct BindedType
struct BindedType : Expression
{
const Varible var;
const Constant con;
Expand All @@ -46,29 +57,29 @@ namespace ExpressionBuilder
template<class T>
constexpr auto operator()(T x) const -> BindedType<Varible, Constant>
{
return BindedType<Varible, Constant>(var, con);
return BindedType<Varible, Constant>(var.template operator()(x), con.template operator()(x));
}
};

template<char Name>
template<class IdentifierName>
struct VaribleType : Expression
{
template<class UnderlyingType>
constexpr auto operator=(UnderlyingType c) const -> BindedType<VaribleType<Name>, ConstantType<UnderlyingType>>
template<class T>
constexpr auto operator=(T c) const -> BindedType<VaribleType<IdentifierName>, decltype(varcon(c))>
{
return BindedType<VaribleType<Name>, ConstantType<UnderlyingType>>(VaribleType<Name>(), ConstantType<UnderlyingType>(c));
return BindedType<VaribleType<IdentifierName>, decltype(varcon(c))>(VaribleType<IdentifierName>(), varcon(c));
}

template<class UnderlyingType>
constexpr auto operator()(BindedType<VaribleType<Name>, ConstantType<UnderlyingType>> x) const -> UnderlyingType
template<class T>
constexpr auto operator()(BindedType<VaribleType<IdentifierName>, T> x) const -> decltype(x.con(x))
{
return x.con.c;
return x.con(x);
}

template<class T>
constexpr auto operator()(T x) const -> VaribleType<Name>
constexpr auto operator()(T x) const -> VaribleType<IdentifierName>
{
return VaribleType<Name>();
return VaribleType<IdentifierName>(); // *this
}
};

Expand All @@ -80,17 +91,6 @@ namespace ExpressionBuilder
constexpr BinaryOperator(Exp1 a, Exp2 b) : _1(a), _2(b) {}
};

template<class T>
constexpr auto varcon(T x) -> typename std::enable_if<!IsExpression<T>::value, ConstantType<T>>::type
{
return ConstantType<T>(x);
}
template<class T>
constexpr auto varcon(T x) -> typename std::enable_if<IsExpression<T>::value, T>::type
{
return x;
}

template<class Exp1, class Exp2>
struct OperatorPlus_t : BinaryOperator<Exp1, Exp2>
{
Expand Down Expand Up @@ -134,25 +134,48 @@ namespace ExpressionBuilder
{
return OperatorPlus_t<decltype(varcon(_1)), decltype(varcon(_2))>(varcon(_1), varcon(_2));
}
template<class T1, class T2>
constexpr auto operator+(ConstantType<T1> _1, ConstantType<T2> _2) -> ConstantType<decltype(_1.c + _2.c)>
{
return ConstantType<decltype(_1.c + _2.c)>(_1.c + _2.c);
}
template<class Exp1, class Exp2, class = typename std::enable_if<IsExpression<Exp1>::value || IsExpression<Exp2>::value>::type>
constexpr auto operator-(Exp1 _1, Exp2 _2) -> OperatorMinus_t<decltype(varcon(_1)), decltype(varcon(_2))>
{
return OperatorMinus_t<decltype(varcon(_1)), decltype(varcon(_2))>(varcon(_1), varcon(_2));
}
template<class T1, class T2>
constexpr auto operator-(ConstantType<T1> _1, ConstantType<T2> _2) -> ConstantType<decltype(_1.c - _2.c)>
{
return ConstantType<decltype(_1.c - _2.c)>(_1.c - _2.c);
}
template<class Exp1, class Exp2, class = typename std::enable_if<IsExpression<Exp1>::value || IsExpression<Exp2>::value>::type>
constexpr auto operator*(Exp1 _1, Exp2 _2) -> OperatorMul_t<decltype(varcon(_1)), decltype(varcon(_2))>
{
return OperatorMul_t<decltype(varcon(_1)), decltype(varcon(_2))>(varcon(_1), varcon(_2));
}
template<class T1, class T2>
constexpr auto operator*(ConstantType<T1> _1, ConstantType<T2> _2) -> ConstantType<decltype(_1.c * _2.c)>
{
return ConstantType<decltype(_1.c * _2.c)>(_1.c * _2.c);
}
template<class Exp1, class Exp2, class = typename std::enable_if<IsExpression<Exp1>::value || IsExpression<Exp2>::value>::type>
constexpr auto operator/(Exp1 _1, Exp2 _2) -> OperatorDiv_t<decltype(varcon(_1)), decltype(varcon(_2))>
{
return OperatorDiv_t<decltype(varcon(_1)), decltype(varcon(_2))>(varcon(_1), varcon(_2));
}
template<class T1, class T2>
constexpr auto operator/(ConstantType<T1> _1, ConstantType<T2> _2) -> ConstantType<decltype(_1.c / _2.c)>
{
return ConstantType<decltype(_1.c / _2.c)>(_1.c / _2.c);
}
class x_id;
class y_id;
class z_id;
}

using detail::VaribleType;
constexpr const detail::VaribleType<'x'> x{};
constexpr const detail::VaribleType<'y'> y{};
constexpr const detail::VaribleType<'z'> z{};
constexpr const detail::VaribleType<detail::x_id> x{};
constexpr const detail::VaribleType<detail::y_id> y{};
constexpr const detail::VaribleType<detail::z_id> z{};
}
12 changes: 9 additions & 3 deletions dlls/weapons/WeaponDataVaribles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@ GNU General Public License for more details.
namespace WeaponTemplate {
namespace Varibles
{
constexpr auto A = ExpressionBuilder::VaribleType<'A'>{};
constexpr auto T = ExpressionBuilder::VaribleType<'T'>{};
constexpr auto N = ExpressionBuilder::VaribleType<'N'>{};
namespace detail
{
class id_A;
class id_T;
class id_N;
}
constexpr auto A = ExpressionBuilder::VaribleType<detail::id_A>{};
constexpr auto T = ExpressionBuilder::VaribleType<detail::id_T>{};
constexpr auto N = ExpressionBuilder::VaribleType<detail::id_N>{};
}
}

0 comments on commit ddd49af

Please sign in to comment.