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/loom/Loom_interface.h"
13
#include "simodo/bormental/DrBormental.h"
14
#include "simodo/inout/convert/functions.h"
21
#define SemanticFiber_DEBUG_no
23
namespace simodo::interpret
27
inout::Reporter_abstract & m,
28
loom::Loom_interface & loom,
29
inout::uri_set_t files,
30
const ast::Node & code,
31
SemanticModules hosts)
36
, _logistics(null_logistics)
39
for(auto host : _hosts)
40
host->setInterpret(this);
42
/// \note PVS Studio err fixed: V1053 Calling the 'addFlowLayer' virtual function in the
43
/// constructor may lead to unexpected result at runtime.
45
addFlowLayer_internal(code, UNDEFINED_BOUNDARY_INDEX, nullptr);
50
inout::Reporter_abstract & m,
51
loom::Loom_interface & loom,
52
SemanticFactories semantic_factories,
53
Logistics_interface & logistics)
57
, _semantic_factories(semantic_factories)
58
, _logistics(logistics)
61
// std::cerr << "Interpret::Interpret 1" << std::endl;
63
for(auto f : _semantic_factories) {
64
SemanticModule_interface * s = f->create(*this);
66
s->setInterpret(this);
71
// std::cerr << "Interpret::Interpret 2" << std::endl;
75
Interpret::~Interpret()
81
void Interpret::addFlowLayer(const ast::Node & code,
82
boundary_index_t boundary_index,
83
std::function<void (const FlowLayerInfo &)> on_layer_end)
85
if (boundary_index == UNDEFINED_BOUNDARY_INDEX)
86
boundary_index = stack().currentBoundary();
88
addFlowLayer_internal(code, boundary_index, on_layer_end);
91
bool Interpret::flushLayers(const ast::Node & code, bool invoke_callback)
93
for(size_t flush_depth = _layer_stack.size()-1; flush_depth < _layer_stack.size(); --flush_depth)
94
if (&_layer_stack[flush_depth].code_flow == &code) {
95
boundary_index_t boundary_index = flush_depth == _layer_stack.size()-1
96
? UNDEFINED_BOUNDARY_INDEX
97
: _layer_stack[flush_depth+1].boundary_index;
98
size_t flushed_count = _layer_stack.size() - flush_depth;
99
FlowLayerInfo flow_info = _layer_stack[flush_depth];
101
for(size_t i = 0; i < flushed_count; ++i)
102
_layer_stack.pop_back();
104
if (boundary_index != UNDEFINED_BOUNDARY_INDEX)
105
stack().clearBoundary(boundary_index);
108
flow_info.on_layer_end(flow_info);
116
void Interpret::instantiateSemantics(SemanticModules hosts)
118
for(auto host : hosts)
119
_hosts.push_back(host);
121
for(auto host : _hosts)
122
host->setInterpret(this);
125
void Interpret::addFile(const std::string & path_to_file)
127
if (std::find(_files.begin(), _files.end(), path_to_file) == _files.end())
128
_files.push_back(path_to_file);
131
bool Interpret::execute(const ast::Node & code)
133
if (!_layer_stack.empty())
136
addFlowLayer(code, UNDEFINED_BOUNDARY_INDEX, nullptr);
139
return _layer_stack.empty();
142
loom::FiberStatus Interpret::executeOperation()
147
const ast::Node * Interpret::lookupOperationNode(int shift, boundary_index_t bound) const
149
if (_layer_stack.empty())
152
const FlowLayerInfo * p_flow = nullptr;
154
if (bound >= _stack.boundaries().size())
155
// Если граница не задана, берём верхний, т.е. рабочий слой
156
p_flow = & _layer_stack.back();
157
else if (_layer_stack.front().boundary_index == bound) {
158
// Если граница на первом уровне - это не штатный режим.
159
// Значит был параллельный вызов, скорее всего, вызывающая сторона находится в другом потоке
162
if (_stack.boundaries()[bound].mark != BOUNDARY_MARK_FUNCTION_FRAME)
163
// Корневой вызов - ищем первый вызов функции
164
for (size_t ib=bound+1; ib < _stack.boundaries().size(); ++ib)
165
if (_stack.boundaries()[ib].mark == BOUNDARY_MARK_FUNCTION_FRAME) {
170
// Если граница принадлежит функции, то берём слой под ним
171
for(size_t i=1; i < _layer_stack.size(); ++i)
172
if (_layer_stack[i].boundary_index == bound) {
173
p_flow = & _layer_stack[i-1];
181
size_t index = p_flow->flow_index + shift;
183
if (index >= p_flow->code_flow.branches().size())
186
return & p_flow->code_flow.branches()[index];
189
boundary_index_t Interpret::copyBaseBounds(const StackOfNames_interface & another_stack)
191
stack().startBoundary(BoundScope::Global, BOUNDARY_MARK_MODULE_FRAME);
193
auto [begin, end] = another_stack.boundaryLowAndTop(0);
195
for(name_index_t i=begin; i < end; ++i)
196
stack().push(another_stack.variable(i).copyVariable());
198
_stack.globals() = another_stack.globals();
200
return stack().startBoundary(BoundScope::Global, BOUNDARY_MARK_MODULE_FRAME);
203
void Interpret::addFlowLayer_internal(const ast::Node & code,
204
boundary_index_t boundary_index,
205
std::function<void (const FlowLayerInfo &)> on_layer_end)
207
if (!code.branches().empty())
208
_layer_stack.push_back({code,on_layer_end,boundary_index});
209
else if (on_layer_end)
210
on_layer_end({code,on_layer_end,boundary_index}); // Например, метод без параметров