-
Notifications
You must be signed in to change notification settings - Fork 0
/
builtinfunctions.hpp
202 lines (160 loc) · 4.52 KB
/
builtinfunctions.hpp
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#ifndef builtinfunctions_hpp_
#define builtinfunctions_hpp_
#include "scope.hpp"
#include "tokenizer.hpp"
#include "interpreter.hpp"
#include <memory>
namespace builtins {
template<typename t>
class PrimitiveType;
using Number=PrimitiveType<uint_least64_t>;
using Bool=PrimitiveType<bool>;
template<typename t>
struct traits {
static obj_ptr print(obj_ptr scope, Arguments& args) {
std::cout<<"PRINTING VALUE ";
std::cout<<((t*)scope.get())->value;
std::cout<<std::endl;
return scope;
}
};
template<>
struct traits<Bool> {
static obj_ptr print(obj_ptr scope, Arguments& args);
};
obj_ptr cond(obj_ptr scope, Arguments& args);
obj_ptr while_(obj_ptr scope, Arguments& args);
obj_ptr for_(obj_ptr scope, Arguments& args);
template<typename t>
inline obj_ptr increment(obj_ptr scope, Arguments& args) {
++((t*)scope.get())->value;
return scope;
}
template<typename t>
inline obj_ptr plus(obj_ptr scope, Arguments& args) {
obj_ptr val=args.execute(scope);
((t*)scope.get())->value+=((t*)val.get())->value;
return scope;
}
template<typename t>
inline obj_ptr times(obj_ptr scope, Arguments& args) {
obj_ptr val=args.execute(scope);
((t*)scope.get())->value*=((t*)val.get())->value;
return scope;
}
inline obj_ptr hello(obj_ptr scope, Arguments& args) {
std::cout<<"HELLO WORLD"<<std::endl;
return scope;
}
// creates method callable object
class Method {
public:
Method(Arguments&& args_): args{std::move(args_)} {};
Method(const Arguments& args_): args{args_} {};
obj_ptr operator()(obj_ptr scope, Arguments& args);
private:
Arguments args;
};
inline obj_ptr createMethod(obj_ptr scope, Arguments& args) {
auto func=std::make_shared<Function<Method>>(Method(args));
return func;
}
template<typename t>
class PrimitiveType: public Object {
public:
PrimitiveType(): value{} {};
PrimitiveType(t&& v): value{v} {};
PrimitiveType(const t& v): value{v} {};
PrimitiveType(PrimitiveType&& f) noexcept = default;
PrimitiveType(const PrimitiveType& f) = delete;
PrimitiveType& operator=(PrimitiveType&& f) noexcept = default;
PrimitiveType& operator=(const PrimitiveType& f) = delete;
virtual ~PrimitiveType() {};
t value;
obj_ptr clone() const override {
obj_ptr new_obj=std::make_shared<PrimitiveType<t>>(value);
cloneScope(new_obj);
return new_obj;
}
};
obj_ptr new_bool(bool val, obj_ptr upper);
template<typename t>
inline obj_ptr equality(obj_ptr scope, Arguments& args) {
obj_ptr val=args.execute(scope);
if(((t*)scope.get())->value==((t*)val.get())->value)
return new_bool(true, scope->getUpperScope());
return new_bool(false, scope->getUpperScope());
}
template<typename t, typename f>
class Operator {
public:
Operator(f comp_): comp{comp_} {};
Operator(const Operator& o) = default;
Operator(Operator&& o) = default;
Operator& operator=(const Operator& o) = default;
Operator& operator=(Operator&& o) = default;
obj_ptr operator()(obj_ptr scope, Arguments& args) {
obj_ptr val=args.execute(scope);
if(comp(((t*)scope.get())->value, ((t*)val.get())->value))
return new_bool(true, scope->getUpperScope());
return new_bool(false, scope->getUpperScope());
}
private:
f comp;
};
template<typename t>
using operator_t = builtins::Operator<Number, bool (*) (t, t)>;
template<typename t>
inline bool eq(t a, t b) {
return a==b;
}
template<typename t>
inline bool neq(t a, t b) {
return a!=b;
}
template<typename t>
inline bool gt(t a, t b) {
return a>b;
}
template<typename t>
inline bool ge(t a, t b) {
return a>=b;
}
template<typename t>
inline bool lt(t a, t b) {
return a<b;
}
template<typename t>
inline bool le(t a, t b) {
return a<=b;
}
template<typename t>
void add_operators(obj_ptr new_no) {
std::vector<std::pair<std::string, bool (*) (t,t)>> ops =
{{"==", eq<t>},
{"!=", neq<t>},
{"<", lt<t>},
{"<=", le<t>},
{">", gt<t>},
{">=", ge<t>}};
for(auto && op: ops) {
new_no->addIntoSlot(op.first,
std::make_shared<Function<operator_t<t>>>(operator_t<t>(op.second)));
}
}
inline obj_ptr new_number(int val, obj_ptr upper) {
auto new_no=std::make_shared<builtins::Number>(val);
new_no->addIntoSlot("print",
std::make_shared<Function<func_ptr>>(traits<Number>::print));
new_no->addIntoSlot("++",
std::make_shared<Function<func_ptr>>(builtins::increment<Number>));
new_no->addIntoSlot("+",
std::make_shared<Function<func_ptr>>(builtins::plus<Number>));
new_no->addIntoSlot("*",
std::make_shared<Function<func_ptr>>(builtins::times<Number>));
add_operators<int>(new_no);
new_no->addUpperScope(upper);
return new_no;
}
};
#endif