4
Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
6
https://bmstu.codes/lsx/simodo
9
#include "simodo/interpret/Interpret.h"
10
#include "simodo/interpret/AnalyzeException.h"
12
#include "simodo/bormental/DrBormental.h"
13
#include "simodo/inout/convert/functions.h"
14
#include "simodo/inout/format/fmt.h"
19
#define SemanticFiber_DEBUG_no
21
namespace simodo::interpret
23
loom::FiberStatus Interpret::start()
25
InterpretState state = InterpretState::Flow;
27
for(auto h : _hosts) {
28
if (h->before_start() != InterpretState::Flow) {
29
state = InterpretState::Complete;
36
loom::FiberStatus Interpret::tieKnot()
38
_waiting_for = nullptr;
41
if (_layer_stack.empty())
42
return loom::FiberStatus::Complete;
44
_layer_stack.back().index = flow().internal_work_index;
46
assert(flow().index < flow().code.branches().size());
48
_layer_stack.back().internal_work_index += 1;
50
const ast::Node & node = flow().code.branches()[flow().index];
52
if (checkBreakPoint(node))
53
return loom::FiberStatus::Paused;
55
#ifndef SemanticFiber_DEBUG
59
/// \todo Оптимизация на случай большого кол-ва семантических модулей :)
60
/// В данном случае можно было бы упростить
62
const std::u16string & current_host_name = node.host();
64
if (_last_host_name != current_host_name) {
65
auto it_host = std::find_if(_hosts.begin(), _hosts.end(),
66
[current_host_name](SemanticModule_interface *h)
68
return h->checkSemanticName(current_host_name);
71
if (it_host == _hosts.end()) {
72
std::string semantics_name = inout::toU8(current_host_name);
73
if (semantics_name.empty())
74
semantics_name = "SBL";
75
throw bormental::DrBormental("interpret::Interpret::tieKnot",
76
inout::fmt("Владелец семантики '%1' не определён")
77
.arg(semantics_name));
80
_last_host_name = current_host_name;
81
_last_host = *it_host;
84
_last_host->performOperation(node);
87
if (flow().internal_work_index < flow().code.branches().size())
90
FlowLayerInfo flow_info = flow();
92
_layer_stack.pop_back();
94
if (flow_info.on_layer_end) {
95
/// \todo Нужно добавить обработку возвращаемого значения, чтобы можно было управлять выполнением
96
/// \todo Нужно убедиться, что в нештатных ситуациях, но при продолжении выполнения, вызов функции будет произведён
97
flow_info.on_layer_end(flow_info);
100
if (_layer_stack.empty())
104
#ifndef SemanticFiber_DEBUG
106
catch (const AnalyzeException & e)
108
_m.reportError(e.location(), e.what());
110
return loom::FiberStatus::Complete;
112
catch (const bormental::DrBormental & e)
114
_m.reportError( node.token().makeLocation(files()),
115
inout::fmt("Произошло исключение в методе %1 при обработке оператора %2\nОписание исключения: %3")
117
.arg(makeOperatorString(node))
120
return _stop_by_error ? loom::FiberStatus::Paused : loom::FiberStatus::Complete;
122
catch (const std::exception & e)
124
_m.reportError( node.token().makeLocation(files()),
125
inout::fmt("Произошло исключение при обработке оператора %1\nОписание исключения: %2" )
126
.arg(makeOperatorString(node))
129
return _stop_by_error ? loom::FiberStatus::Paused : loom::FiberStatus::Complete;
133
_m.reportError(node.token().makeLocation(files()),
134
inout::fmt("Произошло исключение при обработке оператора %1")
135
.arg(makeOperatorString(node)));
137
return _stop_by_error ? loom::FiberStatus::Paused : loom::FiberStatus::Complete;
141
return loom::FiberStatus::Delayed;
143
return _layer_stack.empty() ? loom::FiberStatus::Complete : loom::FiberStatus::Flow;
146
void Interpret::finish()
148
for(auto h : _hosts) {
149
if (h->before_finish(InterpretState::Flow) != InterpretState::Flow)
154
bool Interpret::isReady() const
156
return !_layer_stack.empty();
159
const loom::Fiber_interface * Interpret::getWaitingFor()
164
std::u16string Interpret::makeOperatorString(const ast::Node & operation_node)
166
return (operation_node.host().empty()) ? u"SBL" : operation_node.host() +
167
u"(" + inout::toU16(std::to_string(static_cast<int>(operation_node.operation()))) +
168
u", '" + operation_node.token().lexeme() + u"')";
171
bool Interpret::checkBreakPoint(const ast::Node & node)
173
/// \todo Нужно исключить повторные проверки для одной и той же строки (и файла), которые бывают часто
175
inout::uri_index_t uri_index = node.token().location().uri_index();
176
inout::position_line_t line = node.token().location().range().start().line()+1;
178
if (uri_index >= _files.size())
181
const std::string & uri = _files[uri_index];
183
auto it = std::find_if(_breakpoints.begin(), _breakpoints.end(),
184
[uri, line](const BreakPoint & bp){
185
return uri.find(bp.uri) != std::string::npos && bp.line == line;
188
if (it == _breakpoints.end())
191
_breakpoints.erase(it);