loom

Форк
0
/
AstFormationModule.cpp 
308 строк · 12.5 Кб
1
/*
2
MIT License
3

4
Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
5

6
https://bmstu.codes/lsx/simodo/loom
7
*/
8

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"
13

14
#include "simodo/bormental/DrBormental.h"
15

16
// #include "simodo/interpret/script/ScriptOperationCode.h"
17

18
#include <cassert>
19

20
#define LOGGER_no
21

22
namespace simodo::interpret::builtins
23
{
24
    namespace
25
    {
26
    #ifdef LOGGER
27
        AReporter *  logger_  = nullptr;
28
    #endif
29

30
        variable::Value addNode(variable::Module_interface * host, const variable::VariableSetWrapper & args)
31
        {
32
    #ifdef LOGGER
33
            if (logger_ != nullptr)
34
                logger_->reportInformation(u"/tAststb::addNode");
35
    #endif
36
            assert(host != nullptr);
37
            AstFormationModule & stb = *(static_cast<AstFormationModule *>(host));
38

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();
42

43
            if (index_var.type() == variable::ValueType::Int)
44
            {
45
                int64_t index = index_var.value().getInt();
46

47
                assert((&stb.current_pattern()) != nullptr);
48
                assert((&stb.current_production()) != nullptr);
49

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"));
53

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()
58
                              );
59
            }
60
            else {
61
                inout::Token   token = inout::null_token;
62

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() };
68
                }
69
                else if (index_var.type() == variable::ValueType::Null)
70
                    token = { inout::LexemeType::Punctuation, u"null", index_var.location() };
71
                else
72
                    throw bormental::DrBormental("addNode", inout::fmt("Invalid index type"));
73

74
                stb().addNode(host_var.value().getString(),
75
                            static_cast<ast::OperationCode>(op_var.value().getInt()),
76
                            token,
77
                            token
78
                            );
79
            }
80

81
            return {};
82
        }
83

84
        variable::Value addNode_once(variable::Module_interface * host, const variable::VariableSetWrapper & args)
85
        {
86
    #ifdef LOGGER
87
            if (logger_ != nullptr)
88
                logger_->reportInformation(u"/tAststb::addNode_once");
89
    #endif
90
            assert(host != nullptr);
91
            AstFormationModule & stb = *(static_cast<AstFormationModule *>(host));
92

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;
97

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())];
102

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())
107
                    return {};
108

109
            return addNode(host, args);
110
        }
111

112
        variable::Value addNode_StepInto(variable::Module_interface * host, const variable::VariableSetWrapper & args)
113
        {
114
    #ifdef LOGGER
115
            if (logger_ != nullptr)
116
                logger_->reportInformation(u"/tAststb::addNode_StepInto");
117
    #endif
118
            assert(host != nullptr);
119
            AstFormationModule & stb = *(static_cast<AstFormationModule *>(host));
120

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();
124

125
            if (index_var.type() == variable::ValueType::String)
126
            {
127
                std::u16string value { index_var.value().getString() };
128
                inout::Token   token { inout::LexemeType::Id, value, index_var.location() };
129

130
                stb().addNode_StepInto(host_var.value().getString(),
131
                              static_cast<ast::OperationCode>(op_var.value().getInt()),
132
                              token,
133
                              token
134
                              );
135
            }
136
            else if (index_var.type() == variable::ValueType::Int)
137
            {
138
                int64_t index = index_var.value().getInt();
139

140
                assert((&stb.current_pattern()) != nullptr);
141
                assert((&stb.current_production()) != nullptr);
142

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"));
146

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()
151
                              );
152
            }
153
            else
154
                throw bormental::DrBormental("addNode_StepInto", inout::fmt("Invalid index type"));
155

156
            return {};
157
        }
158

159
        variable::Value goParent(variable::Module_interface * host, const variable::VariableSetWrapper & )
160
        {
161
    #ifdef LOGGER
162
            if (logger_ != nullptr)
163
                logger_->reportInformation(u"/tAststb::goParent");
164
    #endif
165
            assert(host != nullptr);
166
            AstFormationModule & stb = *(static_cast<AstFormationModule *>(host));
167

168
            bool ok = stb().goParent();
169

170
            if (!ok)
171
                throw bormental::DrBormental("goParent", inout::fmt("Invalid rollback of AST nesting"));
172

173
            return {};
174
        }
175

176
        variable::Value setStreamNo(variable::Module_interface * host, const variable::VariableSetWrapper & args)
177
        {
178
    #ifdef LOGGER
179
            if (logger_ != nullptr)
180
                logger_->reportInformation(u"/tAststb::setStreamNo");
181
    #endif
182
            assert(host != nullptr);
183
            AstFormationModule & stb = *(static_cast<AstFormationModule *>(host));
184

185
            int64_t no = args[0].origin().value().getInt();
186

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())));
191

192
            // Номер потока 0 используется для отката к последнему номеру, т.к.
193
            // в языке fuze не предусмотрены отрицательные константы :)
194
            no -= 1;
195
            if (no < 0) {
196
                if (stb.stream_no_history().empty())
197
                    throw bormental::DrBormental("setStream", 
198
                                                inout::fmt("Invalid thread number rollback call"));
199
                no = stb.rollbackStreamNo();
200
            }
201
            else
202
                stb.memorizeStreamNo(no);
203

204
            stb.setCurrentStreamNo(no);
205

206
            return {};
207
        }
208

209
        // static variable::VariableSet_t hosts;
210
    }
211

212
    using namespace simodo::variable;
213

214
    AstFormationModule::AstFormationModule()
215
        // : _hosts(hosts)
216
    {
217
        memorizeStreamNo(ast::DEFAULT_STREAM_NO);
218
    }
219

220
    AstFormationModule::AstFormationModule(variable::VariableSet_t & hosts)
221
        : _hosts(hosts)
222
    {
223
        memorizeStreamNo(ast::DEFAULT_STREAM_NO);
224
    }
225

226
    uint16_t AstFormationModule::rollbackStreamNo()
227
    {
228
        assert(!_stream_no_history.empty());
229

230
        _stream_no_history.pop_back();
231

232
        assert(!_stream_no_history.empty());
233

234
        return _stream_no_history.back();
235
    }
236

237
    void AstFormationModule::memorizeStreamNo(uint16_t no)
238
    {
239
        _stream_no_history.push_back(no);
240
    }
241

242
    const ast::Node & AstFormationModule::current_root() const
243
    {
244
        return _helper.getStream(_helper.getStreamNo()).tree().root();
245
    }
246

247
    variable::Value AstFormationModule::instantiate(std::shared_ptr<variable::Module_interface> module_host)
248
    {
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},
257
            }}}},
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},
265
            }}}},
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},
273
            }}}},
274
            {u"goParent", {ValueType::Function, variable::Object {{
275
                {u"@", ExternalFunction {{module_host}, goParent}},
276
                {u"", ValueType::Null},
277
            }}}},
278
            {u"setStream", {ValueType::Function, variable::Object {{
279
                {u"@", ExternalFunction {{module_host}, setStreamNo}},
280
                {u"", ValueType::Null},
281
                {u"no", ValueType::Int},
282
            }}}},
283
            {u"Stream", variable::Object {{
284
                {u"Default", static_cast<int64_t>(ast::DEFAULT_STREAM_NO)},
285
            }}},
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)},
296
            }}},
297
            {u"host", variable::Object {{
298
                {u"SBL", u""},
299
                {u"fuze", u"fuze"},
300
            }}},
301
        }};
302

303
        ret.insert(ret.end(), _hosts.begin(), _hosts.end());
304

305
        return ret;
306
    }
307

308
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.