-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtagless.cpp
More file actions
141 lines (100 loc) · 2.18 KB
/
tagless.cpp
File metadata and controls
141 lines (100 loc) · 2.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <string>
#include <functional>
#include <iostream>
#include <sstream>
namespace v1 {
auto lit(int i) {
return [=](auto lit, auto add) {
return lit(i);
};
}
template<class A, class B>
auto add(A a, B b) {
return [=](auto lit, auto add) {
return add(a(lit, add), b(lit, add));
};
}
}
namespace v2 {
// auto lit(int i) {
// return [=](auto self) {
// return self.lit(i);
// };
// }
// template<class A, class B>
// auto add(auto self) {
// return [=](auto self) {
// return self.add(a(self , b(lit, add));
// };
// }
}
template<class T>
struct ast {
virtual T lit(int) const = 0;
virtual T add(T, T) const = 0;
};
template<class T>
auto lit(int i) {
return [=](const ast<T>& self) {
return self.lit(i);
};
}
template<class T>
auto add(T lhs, T rhs) {
return [=](const ast<T>& self) {
return self.add(lhs, rhs);
};
}
struct printer: ast<std::string> {
std::string lit(int i) const override { return std::to_string(i); }
std::string add(std::string lhs, std::string rhs) const override {
return lhs + " + " + rhs;
}
};
// reader monad
static const auto pure = [](auto value) {
return [value](const auto&) { return value; };
};
static const auto bind = [](auto ma, auto f) {
return [=](const auto& env) {
const auto a = ma(env);
const auto mb = f(a);
return mb(env);
};
};
template<class MA, class F>
static auto operator>>=(MA ma, F f) {
return bind(ma, f);
}
template<class T>
std::function<T(const ast<T>&)> parse(std::istream& in) {
const auto pos = in.tellg();
int i;
if(in >> i) {
return lit<T>(i);
}
in.clear();
in.seekg(pos);
std::string s;
if(in >> s) {
if(s == "+") {
return parse<T>(in) >>= [&](T lhs) {
return parse<T>(in) >>= [&](T rhs) {
return add(lhs, rhs);
};
};
}
}
throw std::runtime_error("parse error");
}
int main(int argc, char** argv) {
if(argc <= 1) return -1;
std::stringstream ss(argv[1]);
auto expr = parse<std::string>(ss)(printer());
std::cout << expr << std::endl;
{
using namespace v1;
auto x = add(lit(1), lit(2));
}
return 0;
}