4
Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
6
https://bmstu.codes/lsx/simodo/loom
9
#include "simodo/interpret/builtins/modules/AstFormationModule.h"
10
#include "simodo/variable/VariableSetWrapper.h"
11
#include "simodo/parser/fuze/BaseOperationCode.h"
12
#include "simodo/inout/format/fmt.h"
14
#include "simodo/bormental/DrBormental.h"
16
// #include "simodo/interpret/script/ScriptOperationCode.h"
22
namespace simodo::interpret::builtins
27
AReporter * logger_ = nullptr;
30
variable::Value addNode(variable::Module_interface * host, const variable::VariableSetWrapper & args)
33
if (logger_ != nullptr)
34
logger_->reportInformation(u"/tAststb::addNode");
36
assert(host != nullptr);
37
AstFormationModule & stb = *(static_cast<AstFormationModule *>(host));
39
const variable::Variable & host_var = args[0].origin();
40
const variable::Variable & op_var = args[1].origin();
41
const variable::Variable & index_var = args[2].origin();
43
if (index_var.type() == variable::ValueType::Int)
45
int64_t index = index_var.value().getInt();
47
assert((&stb.current_pattern()) != nullptr);
48
assert((&stb.current_production()) != nullptr);
50
if (index < 0 || index >= static_cast<int64_t>(stb.current_pattern().size()))
51
throw bormental::DrBormental("addNode",
52
inout::fmt("Index going beyond the product pattern"));
54
stb().addNode(host_var.value().getString(),
55
static_cast<ast::OperationCode>(op_var.value().getInt()),
56
stb.current_pattern()[static_cast<size_t>(index)],
57
stb.current_production()
61
inout::Token token = inout::null_token;
63
if (index_var.type() == variable::ValueType::String)
64
token = { inout::LexemeType::Id, index_var.value().getString(), index_var.location() };
65
else if (index_var.type() == variable::ValueType::Bool) {
66
bool value = index_var.value().getBool();
67
token = { inout::LexemeType::Punctuation, value ? u"true" : u"false", index_var.location() };
69
else if (index_var.type() == variable::ValueType::Null)
70
token = { inout::LexemeType::Punctuation, u"null", index_var.location() };
72
throw bormental::DrBormental("addNode", inout::fmt("Invalid index type"));
74
stb().addNode(host_var.value().getString(),
75
static_cast<ast::OperationCode>(op_var.value().getInt()),
84
variable::Value addNode_once(variable::Module_interface * host, const variable::VariableSetWrapper & args)
87
if (logger_ != nullptr)
88
logger_->reportInformation(u"/tAststb::addNode_once");
90
assert(host != nullptr);
91
AstFormationModule & stb = *(static_cast<AstFormationModule *>(host));
93
const variable::Variable & host_var = args[0].origin();
94
const variable::Variable & op_var = args[1].origin();
95
const variable::Variable & index_var = args[2].origin();
96
inout::Token token = inout::null_token;
98
if (index_var.type() == variable::ValueType::String)
99
token = { inout::LexemeType::Id, index_var.value().getString(), index_var.location() };
100
else if (index_var.type() == variable::ValueType::Int)
101
token = stb.current_pattern()[static_cast<size_t>(index_var.value().getInt())];
103
for(const ast::Node & n : stb.current_root().branches())
104
if (n.host() == host_var.value().getString()
105
&& n.operation() == static_cast<ast::OperationCode>(op_var.value().getInt())
106
&& n.token().lexeme() == token.lexeme())
109
return addNode(host, args);
112
variable::Value addNode_StepInto(variable::Module_interface * host, const variable::VariableSetWrapper & args)
115
if (logger_ != nullptr)
116
logger_->reportInformation(u"/tAststb::addNode_StepInto");
118
assert(host != nullptr);
119
AstFormationModule & stb = *(static_cast<AstFormationModule *>(host));
121
const variable::Variable & host_var = args[0].origin();
122
const variable::Variable & op_var = args[1].origin();
123
const variable::Variable & index_var = args[2].origin();
125
if (index_var.type() == variable::ValueType::String)
127
std::u16string value { index_var.value().getString() };
128
inout::Token token { inout::LexemeType::Id, value, index_var.location() };
130
stb().addNode_StepInto(host_var.value().getString(),
131
static_cast<ast::OperationCode>(op_var.value().getInt()),
136
else if (index_var.type() == variable::ValueType::Int)
138
int64_t index = index_var.value().getInt();
140
assert((&stb.current_pattern()) != nullptr);
141
assert((&stb.current_production()) != nullptr);
143
if (index < 0 || index >= static_cast<int64_t>(stb.current_pattern().size()))
144
throw bormental::DrBormental("addNode_StepInto",
145
inout::fmt("Index going beyond the product pattern"));
147
stb().addNode_StepInto(host_var.value().getString(),
148
static_cast<ast::OperationCode>(op_var.value().getInt()),
149
stb.current_pattern()[static_cast<size_t>(index)],
150
stb.current_production()
154
throw bormental::DrBormental("addNode_StepInto", inout::fmt("Invalid index type"));
159
variable::Value goParent(variable::Module_interface * host, const variable::VariableSetWrapper & )
162
if (logger_ != nullptr)
163
logger_->reportInformation(u"/tAststb::goParent");
165
assert(host != nullptr);
166
AstFormationModule & stb = *(static_cast<AstFormationModule *>(host));
168
bool ok = stb().goParent();
171
throw bormental::DrBormental("goParent", inout::fmt("Invalid rollback of AST nesting"));
176
variable::Value setStreamNo(variable::Module_interface * host, const variable::VariableSetWrapper & args)
179
if (logger_ != nullptr)
180
logger_->reportInformation(u"/tAststb::setStreamNo");
182
assert(host != nullptr);
183
AstFormationModule & stb = *(static_cast<AstFormationModule *>(host));
185
int64_t no = args[0].origin().value().getInt();
187
if (no < 0 || no > int64_t(stb.streams_quantity()))
188
throw bormental::DrBormental("setStream",
189
inout::fmt("Outflow of the stream number beyond the limits [0, %1]")
190
.arg(int64_t(stb.streams_quantity())));
192
// Номер потока 0 используется для отката к последнему номеру, т.к.
193
// в языке fuze не предусмотрены отрицательные константы :)
196
if (stb.stream_no_history().empty())
197
throw bormental::DrBormental("setStream",
198
inout::fmt("Invalid thread number rollback call"));
199
no = stb.rollbackStreamNo();
202
stb.memorizeStreamNo(no);
204
stb.setCurrentStreamNo(no);
209
// static variable::VariableSet_t hosts;
212
using namespace simodo::variable;
214
AstFormationModule::AstFormationModule()
217
memorizeStreamNo(ast::DEFAULT_STREAM_NO);
220
AstFormationModule::AstFormationModule(variable::VariableSet_t & hosts)
223
memorizeStreamNo(ast::DEFAULT_STREAM_NO);
226
uint16_t AstFormationModule::rollbackStreamNo()
228
assert(!_stream_no_history.empty());
230
_stream_no_history.pop_back();
232
assert(!_stream_no_history.empty());
234
return _stream_no_history.back();
237
void AstFormationModule::memorizeStreamNo(uint16_t no)
239
_stream_no_history.push_back(no);
242
const ast::Node & AstFormationModule::current_root() const
244
return _helper.getStream(_helper.getStreamNo()).tree().root();
247
variable::Value AstFormationModule::instantiate(std::shared_ptr<variable::Module_interface> module_host)
249
variable::VariableSet_t ret {{
250
{u"addNode", {ValueType::Function, variable::Object {{
251
{u"@", ExternalFunction {{module_host}, addNode}},
252
{u"", ValueType::Null},
253
{u"host", ValueType::String},
254
{u"op", ValueType::Int},
255
// Неопределённый тип для индекса предполагает тип параметра 'any'
256
{u"index", ValueType::Null},
258
{u"addNode_once", {ValueType::Function, variable::Object {{
259
{u"@", ExternalFunction {{module_host}, addNode_once}},
260
{u"", ValueType::Null},
261
{u"host", ValueType::String},
262
{u"op", ValueType::Int},
263
// Неопределённый тип для индекса предполагает тип параметра 'any'
264
{u"index", ValueType::Null},
266
{u"addNode_StepInto", {ValueType::Function, variable::Object {{
267
{u"@", ExternalFunction {{module_host}, addNode_StepInto}},
268
{u"", ValueType::Null},
269
{u"host", ValueType::String},
270
{u"op", ValueType::Int},
271
// Неопределённый тип для индекса предполагает тип параметра 'any'
272
{u"index", ValueType::Null},
274
{u"goParent", {ValueType::Function, variable::Object {{
275
{u"@", ExternalFunction {{module_host}, goParent}},
276
{u"", ValueType::Null},
278
{u"setStream", {ValueType::Function, variable::Object {{
279
{u"@", ExternalFunction {{module_host}, setStreamNo}},
280
{u"", ValueType::Null},
281
{u"no", ValueType::Int},
283
{u"Stream", variable::Object {{
284
{u"Default", static_cast<int64_t>(ast::DEFAULT_STREAM_NO)},
286
{u"op", variable::Object {{
287
{u"None", static_cast<int64_t>(parser::BaseOperationCode::None)},
288
{u"PushConstant", static_cast<int64_t>(parser::BaseOperationCode::PushConstant)},
289
{u"PushVariable", static_cast<int64_t>(parser::BaseOperationCode::PushVariable)},
290
{u"ObjectElement", static_cast<int64_t>(parser::BaseOperationCode::ObjectElement)},
291
{u"FunctionCall", static_cast<int64_t>(parser::BaseOperationCode::FunctionCall)},
292
{u"ProcedureCheck", static_cast<int64_t>(parser::BaseOperationCode::ProcedureCheck)},
293
{u"Print", static_cast<int64_t>(parser::BaseOperationCode::Print)},
294
{u"Block", static_cast<int64_t>(parser::BaseOperationCode::Block)},
295
{u"Pop", static_cast<int64_t>(parser::BaseOperationCode::Pop)},
297
{u"host", variable::Object {{
303
ret.insert(ret.end(), _hosts.begin(), _hosts.end());