Skip to content

Instantly share code, notes, and snippets.

@tiffany352
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tiffany352/2b66929898526b70f8df to your computer and use it in GitHub Desktop.
Save tiffany352/2b66929898526b70f8df to your computer and use it in GitHub Desktop.
/* Copyright 2014 tiffany <tiffany@stormbit.net>
* Licensed under zlib/libpng
*/
#ifndef FRP_HPP
#define FRP_HPP
#include <vector>
#include <functional>
namespace SpaceGame {
// http://stackoverflow.com/a/7943765
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
{
enum { arity = sizeof...(Args) };
typedef ReturnType result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
};
};
template<typename F, typename src>
struct Behaviour;
template<typename F, typename src1, typename src2>
struct Behaviour2;
template<typename T>
struct Variable;
template<typename T>
struct VariableSrc {
VariableSrc() {}
VariableSrc(Variable<T>* src) : src(src) {}
Variable<T> *src;
T get()
{
return src->get();
}
};
template<typename T>
class Variable {
T val;
public:
static VariableSrc<T> Src;
Variable(T v) : val(v) {}
T get()
{
return val;
}
void set(T v)
{
val = v;
}
template<typename F>
Behaviour<F,VariableSrc<T>> lift(F func)
{
return Behaviour<F,VariableSrc<T>>
(func,
VariableSrc<T>(this));
}
};
template<typename T>
struct BehaviourSrc {
BehaviourSrc() = default;
BehaviourSrc(T (*fn)(void*), void *user) : update(fn), user(user) {}
template<typename F, typename src>
BehaviourSrc(Behaviour<F,src> *self) : update(&Behaviour<F,src>::update), user(self) {}
void *user;
T (*update)(void*);
T get()
{
return update(user);
}
};
template<typename F, typename src>
struct Behaviour {
typedef function_traits<F> traits;
typedef typename traits::result_type U;
Behaviour(F f, src source) : func(f), source(source) {}
static BehaviourSrc<U> Src;
F func;
src source;
U get()
{
return func(source.get());
}
static U update(void *ptr)
{
Behaviour<F,src> &self = *reinterpret_cast<Behaviour<F,src>*>(ptr);
return self.get();
}
template<typename F2>
Behaviour<F2,BehaviourSrc<U>> lift(F2 func)
{
return Behaviour<F2,BehaviourSrc<U>>
(func,
BehaviourSrc<U>(this));
}
};
template<typename F, typename src1, typename src2>
struct Behaviour2 {
typedef function_traits<F> traits;
typedef typename traits::result_type U;
Behaviour2(F f, src1 source1, src2 source2) : func(f), source1(source1), source2(source2) {}
static BehaviourSrc<U> Src;
F func;
src1 source1;
src2 source2;
U get()
{
return func(source1.get(), source2.get());
}
static U update(void *ptr)
{
Behaviour2<F,src1,src2> &self = *reinterpret_cast<Behaviour2<F,src1,src2>*>(ptr);
return self.get();
}
template<typename F2>
Behaviour<F2,BehaviourSrc<U>> lift(F2 func)
{
return Behaviour<F2,BehaviourSrc<U>>
(func,
BehaviourSrc<U>(this));
}
};
template<typename F, typename B1, typename B2>
Behaviour2<F,decltype(B1::Src),decltype(B2::Src)> lift2(B1 &b1, B2 &b2, F func)
{
return Behaviour2<F,decltype(B1::Src),decltype(B2::Src)>
(func,
decltype(B1::Src)(&b1),
decltype(B2::Src)(&b2));
}
}
#endif
#include "frp.hpp"
#include <cstdio>
using namespace SpaceGame;
int main()
{
Variable<int> test(4);
auto test_x_2 = test.lift([](int a) -> int {return a*2;});
auto test_plus_1 = test_x_2.lift([](int a) -> int {return a+1;});
auto res = lift2(test_x_2, test_plus_1, [](int a, int b) -> int {return a+b;});
printf("%i\n", res.get()); // 17
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment