-
Notifications
You must be signed in to change notification settings - Fork 0
/
statement.h
383 lines (291 loc) · 14.5 KB
/
statement.h
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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
#pragma once
#include "runtime.h"
#include <functional>
namespace ast {
class ObjectThrow : public std::exception{
public:
ObjectThrow(runtime::ObjectHolder obj);
runtime::ObjectHolder Get();
private:
runtime::ObjectHolder obj_;
};
using Statement = runtime::Executable;
// Выражение, возвращающее значение типа T,
// используется как основа для создания констант
template <typename T>
class ValueStatement : public Statement {
public:
explicit ValueStatement(T v)
: value_(std::move(v)) {
}
runtime::ObjectHolder Execute([[maybe_unused]]runtime::Closure& closure,
[[maybe_unused]]runtime::Context& context) override {
return runtime::ObjectHolder::Share(value_);
}
private:
T value_;
};
using NumericConst = ValueStatement<runtime::Number>;
using StringConst = ValueStatement<runtime::String>;
using BoolConst = ValueStatement<runtime::Bool>;
/*
Вычисляет значение переменной либо цепочки вызовов полей объектов id1.id2.id3.
Например, выражение circle.center.x - цепочка вызовов полей объектов в инструкции:
x = circle.center.x
*/
class VariableValue : public Statement {
public:
explicit VariableValue(const std::string& var_name);
explicit VariableValue(std::vector<std::string> dotted_ids);
runtime::ObjectHolder Execute(runtime::Closure& closure, [[maybe_unused]]runtime::Context& context) override;
private:
std::string var_name_;
std::vector<std::string> dotted_ids_;
};
// Присваивает переменной, имя которой задано в параметре var, значение выражения rv
class Assignment : public Statement {
public:
Assignment(std::string var, std::shared_ptr<Statement> rv);
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
private:
std::string var_;
std::shared_ptr<Statement> rv_;
};
// Присваивает полю object.field_name значение выражения rv
class FieldAssignment : public Statement {
public:
FieldAssignment(VariableValue object, std::string field_name, std::shared_ptr<Statement> rv);
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
VariableValue object_;
std::string field_name_;
std::shared_ptr<Statement> rv_;
};
// Значение None
class None : public Statement {
public:
runtime::ObjectHolder Execute([[maybe_unused]] runtime::Closure& closure,
[[maybe_unused]] runtime::Context& context) override {
return {};
}
};
// Команда print
class Print : public Statement {
public:
Print(std::string name)
: name_(name) {
}
// Инициализирует команду print для вывода значения выражения argument
explicit Print(std::unique_ptr<Statement> argument);
// Инициализирует команду print для вывода списка значений args
explicit Print(std::vector<std::unique_ptr<Statement>> args);
// Инициализирует команду print для вывода значения переменной name
static std::unique_ptr<Print> Variable(const std::string& name);
// Во время выполнения команды print вывод должен осуществляться в поток, возвращаемый из
// context.GetOutputStream()
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
private:
std::unique_ptr<Statement> argument_;
std::vector<std::unique_ptr<Statement>> args_;
std::string name_;
};
// Вызывает метод object.method со списком параметров args
class MethodCall : public Statement {
public:
MethodCall(std::unique_ptr<Statement> object, std::string method,
std::vector<std::unique_ptr<Statement>> args);
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
private:
std::unique_ptr<Statement> object_;
std::string method_;
std::vector<std::unique_ptr<Statement>> args_;
};
/*
Создаёт новый экземпляр класса class_, передавая его конструктору набор параметров args.
Если в классе отсутствует метод __init__ с заданным количеством аргументов,
то экземпляр класса создаётся без вызова конструктора (поля объекта не будут проинициализированы):
class Person:
def set_name(name):
self.name = name
p = Person()
# Поле name будет иметь значение только после вызова метода set_name
p.set_name("Ivan")
*/
class NewInstance : public Statement {
public:
explicit NewInstance(const runtime::Class& class_);
NewInstance(const runtime::Class& class_, std::vector<std::unique_ptr<Statement>> args);
// Возвращает объект, содержащий значение типа ClassInstance
runtime::ObjectHolder Execute([[maybe_unused]] runtime::Closure& closure, [[maybe_unused]] runtime::Context& context) override;
private:
runtime::ObjectHolder obj_;
std::vector<std::unique_ptr<Statement>> args_;
};
// Базовый класс для унарных операций
class UnaryOperation : public Statement {
public:
explicit UnaryOperation(std::unique_ptr<Statement> argument)
: statement_(std::move(argument)) {
}
std::unique_ptr<Statement> statement_;
};
// Операция str, возвращающая строковое значение своего аргумента
class Stringify : public UnaryOperation {
public:
using UnaryOperation::UnaryOperation;
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
};
// Родительский класс Бинарная операция с аргументами lhs и rhs
class BinaryOperation : public Statement {
public:
BinaryOperation(std::unique_ptr<Statement> lhs, std::unique_ptr<Statement> rhs)
: lhs_(std::move(lhs)), rhs_(std::move(rhs)) {
}
std::unique_ptr<Statement> lhs_;
std::unique_ptr<Statement> rhs_;
};
// Возвращает результат операции + над аргументами lhs и rhs
class Add : public BinaryOperation {
public:
using BinaryOperation::BinaryOperation;
// Поддерживается сложение:
// число + число
// строка + строка
// объект1 + объект2, если у объект1 - пользовательский класс с методом _add__(rhs)
// В противном случае при вычислении выбрасывается runtime_error
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
};
// Возвращает результат вычитания аргументов lhs и rhs
class Sub : public BinaryOperation {
public:
using BinaryOperation::BinaryOperation;
// Поддерживается вычитание:
// число - число
// Если lhs и rhs - не числа, выбрасывается исключение runtime_error
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
};
// Возвращает результат умножения аргументов lhs и rhs
class Mult : public BinaryOperation {
public:
using BinaryOperation::BinaryOperation;
// Поддерживается умножение:
// число * число
// Если lhs и rhs - не числа, выбрасывается исключение runtime_error
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
};
// Возвращает результат деления lhs и rhs
class Div : public BinaryOperation {
public:
using BinaryOperation::BinaryOperation;
// Поддерживается деление:
// число / число
// Если lhs и rhs - не числа, выбрасывается исключение runtime_error
// Если rhs равен 0, выбрасывается исключение runtime_error
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
};
// Возвращает результат вычисления логической операции or над lhs и rhs
class Or : public BinaryOperation {
public:
using BinaryOperation::BinaryOperation;
// Значение аргумента rhs вычисляется, только если значение lhs
// после приведения к Bool равно False
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
};
// Возвращает результат вычисления логической операции and над lhs и rhs
class And : public BinaryOperation {
public:
using BinaryOperation::BinaryOperation;
// Значение аргумента rhs вычисляется, только если значение lhs
// после приведения к Bool равно True
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
};
// Возвращает результат вычисления логической операции not над единственным аргументом операции
class Not : public UnaryOperation {
public:
using UnaryOperation::UnaryOperation;
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
};
// Составная инструкция (например: тело метода, содержимое ветки if, либо else)
class Compound : public Statement {
public:
// Конструирует Compound из нескольких инструкций типа unique_ptr<Statement>
template <typename... Args>
explicit Compound([[maybe_unused]]Args&&... args) {
args_.reserve(sizeof...(args));
if constexpr (sizeof...(args)){
ExtractArgs_(std::forward<Args>(args)...);
}
}
// Добавляет очередную инструкцию в конец составной инструкции
void AddStatement(std::unique_ptr<Statement> stmt);
// Последовательно выполняет добавленные инструкции. Возвращает None
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
private:
std::vector<std::unique_ptr<Statement>> args_;
template <typename Arg, typename... Args>
void ExtractArgs_(Arg&& arg, Args&&... args){
args_.push_back(std::move(arg));
if constexpr (sizeof...(args)){
ExtractArgs_(std::forward<Args>(args)...);
}
}
};
// Тело метода. Как правило, содержит составную инструкцию
class MethodBody : public Statement {
public:
explicit MethodBody(std::unique_ptr<Statement>&& body);
// Вычисляет инструкцию, переданную в качестве body.
// Если внутри body была выполнена инструкция return, возвращает результат return
// В противном случае возвращает None
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
private:
std::unique_ptr<Statement> body_;
};
// Выполняет инструкцию return с выражением statement
class Return : public Statement {
public:
explicit Return(std::unique_ptr<Statement> statement)
: statement_(std::move(statement)) {
}
// Останавливает выполнение текущего метода. После выполнения инструкции return метод,
// внутри которого она была исполнена, должен вернуть результат вычисления выражения statement.
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
private:
std::unique_ptr<Statement> statement_;
};
// Объявляет класс
class ClassDefinition : public Statement {
public:
// Гарантируется, что ObjectHolder содержит объект типа runtime::Class
explicit ClassDefinition(runtime::ObjectHolder cls);
// Создаёт внутри closure новый объект, совпадающий с именем класса и значением, переданным в
// конструктор
runtime::ObjectHolder Execute(runtime::Closure& closure, [[maybe_unused]] runtime::Context& context) override;
private:
runtime::ObjectHolder cls_;
};
// Инструкция if <condition> <if_body> else <else_body>
class IfElse : public Statement {
public:
// Параметр else_body может быть равен nullptr
IfElse(std::unique_ptr<Statement> condition, std::unique_ptr<Statement> if_body,
std::unique_ptr<Statement> else_body);
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
private:
std::unique_ptr<Statement> condition_;
std::unique_ptr<Statement> if_body_;
std::unique_ptr<Statement> else_body_;
};
// Операция сравнения
class Comparison : public BinaryOperation {
public:
// Comparator задаёт функцию, выполняющую сравнение значений аргументов
using Comparator = std::function<bool(const runtime::ObjectHolder&,
const runtime::ObjectHolder&, runtime::Context&)>;
Comparison(Comparator cmp, std::unique_ptr<Statement> lhs, std::unique_ptr<Statement> rhs);
// Вычисляет значение выражений lhs и rhs и возвращает результат работы comparator,
// приведённый к типу runtime::Bool
runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
private:
Comparator cmp_;
};
} // namespace ast