Last active
December 16, 2015 06:28
-
-
Save Heimdell/5391469 to your computer and use it in GitHub Desktop.
Compile with `g++ -std=c++11 test.c++`. Use g++ of version 4.7.2 and... patience.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef AUTOWIRE_H | |
#define AUTOWIRE_H | |
#include <map> | |
#include <string> | |
#include <stdexcept> | |
using namespace std; | |
#include "singleton.h" | |
#include "interpolate.h" | |
template <class Key, class Value> | |
struct Autowire | |
{ | |
typedef map<Key, Value> Map; | |
Autowire &assume(Key key, Value &&value) { | |
mapping[key] = value; | |
return *this; | |
} | |
Value &resolve(Key key) { | |
if (mapping.find(key) == mapping.end()) | |
throw domain_error(intercalate(" ", "the key", key, "cannot be resolved")); | |
return mapping[key]; | |
} | |
private: | |
Map mapping; | |
}; | |
template <class Key, class Value> | |
Singleton<Autowire<Key, Value>> &wiring() { return single<Autowire<Key, Value>>(); } | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef CONCAT_H | |
#define CONCAT_H | |
template <class CA, class CB> | |
CA &&concat(CA &&ca, CB &&cb) { | |
ca.insert(end(ca), begin(cb), end(cb)); | |
return ca; | |
} | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef CPU_H | |
#define CPU_H | |
#include "autowire.h" | |
#include "protocol.h" | |
template <class Definition, class Serialized> | |
using opcode = Autowire<Definition, function<Serialized (const Command<Definition> &)>>; | |
template <class Definition, class Serialized> | |
struct Cpu : public opcode<Definition, Serialized> | |
{ | |
typedef Command<Definition> CommandType; | |
Serialized evaluate(const Command<Definition> & cmd) { | |
auto opc = this->resolve(cmd.definition); | |
return opc(cmd); | |
} | |
}; | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef INTERPOLATE_H | |
#define INTERPOLATE_H | |
#include <sstream> | |
#include <string> | |
using namespace std; | |
inline string _interpolate(stringstream &os) { | |
return os.str(); | |
} | |
template <class Head, class... Tail> | |
string _interpolate(stringstream &os, Head head, Tail... tail) { | |
os << head; | |
return _interpolate(os, tail...); | |
} | |
template <class... Args> | |
string interpolate(Args... args) { | |
stringstream os; | |
return _interpolate(os, args...); | |
} | |
template <class... Args> | |
string line(Args... args) { | |
return interpolate(args..., "\n"); | |
} | |
template <class Last> | |
string _intercalate(string, stringstream &os, Last last) { | |
os << last; | |
return os.str(); | |
} | |
template <class Head, class... Tail> | |
string _intercalate(string sep, stringstream &os, Head head, Tail... tail) { | |
os << head << sep; | |
return _intercalate(sep, os, tail...); | |
} | |
template <class... Args> | |
string intercalate(string sep, Args... args) { | |
stringstream os; | |
return _intercalate(sep, os, args...); | |
} | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef LABELLED_H | |
#define LABELLED_H | |
#if 0 | |
template <class, class T> | |
struct Labelled | |
{ | |
T * operator -> () { return &t; } | |
private: | |
T t; | |
}; | |
#else | |
template <class, class T> | |
struct Labelled : public T { }; | |
#endif | |
#define DECLARE_LABEL(Label) struct Label {}; | |
DECLARE_LABEL(Default); | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef PROTOCOL_H | |
#define PROTOCOL_H | |
#include <vector> | |
#include <tuple> | |
#include <list> | |
#include <functional> | |
using namespace std; | |
template <class Definition> | |
void complain_about_params_count(string type, Definition name, int has, int must); | |
template <class Definition> | |
struct Command { | |
Command(Definition definition, | |
vector<int> &&ints, | |
vector<float> &&floats, | |
vector<string> &&strings) | |
: definition(definition), | |
ints (ints), | |
floats (floats), | |
strings (strings) | |
{} | |
Definition definition; | |
vector<int> ints; | |
vector<float> floats; | |
vector<string> strings; | |
#define ASSERT_ARGCOUNT(type) \ | |
void assert_##type##_args_count(int n) const { \ | |
if (type##s.size() < n) \ | |
complain_about_params_count(#type, definition, type##s.size(), n); \ | |
} | |
ASSERT_ARGCOUNT(int); | |
ASSERT_ARGCOUNT(float); | |
ASSERT_ARGCOUNT(string); | |
}; | |
template <class Definition> | |
inline void complain_about_params_count(string type, Definition name, int has, int must) { | |
throw runtime_error( | |
intercalate(" ", | |
"not enouth", | |
type, | |
"params in command", | |
name, | |
":", | |
"there is", | |
has, | |
"but must be at least", | |
must | |
) | |
); | |
} | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef SINGLETON_H | |
#define SINGLETON_H | |
template <class T> | |
struct Singleton : public T { | |
static Singleton &instance() { return _instance; } | |
private: | |
static Singleton _instance; | |
Singleton() { } | |
Singleton(Singleton &&) = delete; | |
Singleton(const Singleton &) = delete; | |
}; | |
template <class T> | |
Singleton<T> Singleton<T>::_instance; | |
template <class T> | |
Singleton<T> &single() { return Singleton<T>::instance(); } | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "streamer.h" | |
#include <iostream> | |
int main() { | |
auto &streamer = single<Streamer<string, char>>(); | |
typedef | |
decay<decltype(streamer)> | |
::type | |
::StreamCpu | |
::CommandType CMD; | |
auto &cpu = streamer.cpu(); | |
cpu | |
.assume("add", | |
[](const CMD &cmd) { | |
cmd.assert_int_args_count(2); | |
return list<char>({ | |
'+', | |
(char) ('0' + cmd.ints[0]), | |
(char) ('0' + cmd.ints[1]) | |
}); | |
}) | |
.assume("nop", | |
[](const CMD &cmd) { | |
return list<char>({ 'X' }); | |
}) | |
.assume("echo", | |
[](const CMD &cmd) { | |
cmd.assert_string_args_count(1); | |
const string &&arg = cmd.strings[0].substr(0, 255); | |
list<char> mark = { '!' }; | |
return concat(mark, interpolate(arg.size(), ">", arg)); | |
}) | |
; | |
list<CMD> commands = { | |
{ "add", {1, 2}, {}, {}}, | |
{ "nop", {}, {}, {}}, | |
{ "echo", {}, {}, {"hello, world"}} | |
}; | |
list<char> packed = streamer.translate(commands); | |
string out; | |
concat(out, packed); | |
cout << out << endl; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef STREAMER_H | |
#define STREAMER_H | |
#include "cpu.h" | |
#include "labelled.h" | |
#include "concat.h" | |
#include <algorithm> | |
template <class Definition, class Cell, class Name = Default> | |
struct Streamer { | |
typedef Cpu<Definition, list<Cell>> StreamCpu; | |
typedef typename StreamCpu::CommandType StreamCommand; | |
template <class T> | |
using Stream = list<T>; | |
Singleton<Labelled<Name, StreamCpu>> &cpu() { return single<Labelled<Name, StreamCpu>>(); } | |
Stream<Cell> translate(Stream<StreamCommand> commands) { | |
auto &cpu = this->cpu(); | |
Stream<Cell> out; | |
for_each( | |
begin(commands), | |
end (commands), | |
[&out, &cpu](StreamCommand command) { | |
list<Cell> part = cpu.evaluate(command); | |
out.insert(out.end(), part.begin(), part.end()); | |
} | |
); | |
return out; | |
} | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment