loom

Форк
0
/
Interpret.cpp 
214 строк · 7.2 Кб
1
/*
2
MIT License
3

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

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

9
#include "simodo/interpret/Interpret.h"
10
#include "simodo/interpret/AnalyzeException.h"
11

12
#include "simodo/loom/Loom_interface.h"
13
#include "simodo/bormental/DrBormental.h"
14
#include "simodo/inout/convert/functions.h"
15

16
#include <algorithm>
17
#include <cassert>
18

19
// #include <iostream>
20

21
#define SemanticFiber_DEBUG_no
22

23
namespace simodo::interpret
24
{
25
    Interpret::Interpret(
26
                    InterpretType type,
27
                    inout::Reporter_abstract & m, 
28
                    loom::Loom_interface & loom, 
29
                    inout::uri_set_t files, 
30
                    const ast::Node & code,
31
                    SemanticModules hosts)
32
        : _type(type)
33
        , _m(m)
34
        , _loom(loom)
35
        , _files(files)
36
        , _logistics(null_logistics)
37
        , _hosts(hosts)
38
    {
39
        for(auto host : _hosts) 
40
            host->setInterpret(this);
41

42
        /// \note PVS Studio err fixed: V1053 Calling the 'addFlowLayer' virtual function in the 
43
        /// constructor may lead to unexpected result at runtime.
44

45
        addFlowLayer_internal(code, UNDEFINED_BOUNDARY_INDEX, nullptr);
46
    }
47

48
    Interpret::Interpret(
49
                    InterpretType type,
50
                    inout::Reporter_abstract & m, 
51
                    loom::Loom_interface & loom, 
52
                    SemanticFactories semantic_factories,
53
                    Logistics_interface & logistics)
54
        : _type(type)
55
        , _m(m)
56
        , _loom(loom)
57
        , _semantic_factories(semantic_factories)
58
        , _logistics(logistics)
59
        , _stack(logistics)
60
    {
61
        // std::cerr << "Interpret::Interpret 1" << std::endl;
62

63
        for(auto f : _semantic_factories) {
64
            SemanticModule_interface * s = f->create(*this);
65
            if (s) {
66
                s->setInterpret(this);
67
                _hosts.push_back(s);
68
            }
69
        }
70

71
        // std::cerr << "Interpret::Interpret 2" << std::endl;
72

73
    }
74

75
    Interpret::~Interpret()
76
    {
77
        for(auto h : _hosts)
78
            delete h;
79
    }
80

81
    void Interpret::addFlowLayer(const ast::Node & code,
82
                                boundary_index_t boundary_index, 
83
                                std::function<void (const FlowLayerInfo &)> on_layer_end)
84
    {
85
        if (boundary_index == UNDEFINED_BOUNDARY_INDEX)
86
            boundary_index = stack().currentBoundary();
87

88
        addFlowLayer_internal(code, boundary_index, on_layer_end);
89
    }
90

91
    bool Interpret::flushLayers(const ast::Node & code, bool invoke_callback)
92
    {
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];
100

101
                for(size_t i = 0; i < flushed_count; ++i)
102
                    _layer_stack.pop_back();
103

104
                if (boundary_index != UNDEFINED_BOUNDARY_INDEX)
105
                    stack().clearBoundary(boundary_index);
106

107
                if (invoke_callback)
108
                    flow_info.on_layer_end(flow_info);
109

110
                return true;
111
            }
112

113
        return false;
114
    }
115

116
    void Interpret::instantiateSemantics(SemanticModules hosts)
117
    {
118
        for(auto host : hosts) 
119
            _hosts.push_back(host);
120

121
        for(auto host : _hosts) 
122
            host->setInterpret(this);
123
    }
124

125
    void Interpret::addFile(const std::string & path_to_file)
126
    {
127
        if (std::find(_files.begin(), _files.end(), path_to_file) == _files.end())
128
            _files.push_back(path_to_file);
129
    }   
130

131
    bool Interpret::execute(const ast::Node & code)
132
    {
133
        if (!_layer_stack.empty())
134
            return false;
135

136
        addFlowLayer(code, UNDEFINED_BOUNDARY_INDEX, nullptr);
137
        _loom.stretch(this);
138
        _loom.wait(); 
139
        return _layer_stack.empty();
140
    }
141

142
    loom::FiberStatus Interpret::executeOperation()
143
    { 
144
        return tieKnot(); 
145
    }
146
                                        
147
    const ast::Node * Interpret::lookupOperationNode(int shift, boundary_index_t bound) const
148
    {
149
        if (_layer_stack.empty())
150
            return nullptr;
151

152
        const FlowLayerInfo * p_flow = nullptr;
153
        
154
        if (bound >= _stack.boundaries().size())
155
            // Если граница не задана, берём верхний, т.е. рабочий слой
156
            p_flow = & _layer_stack.back();
157
        else if (_layer_stack.front().boundary_index == bound) {
158
            // Если граница на первом уровне - это не штатный режим. 
159
            // Значит был параллельный вызов, скорее всего, вызывающая сторона находится в другом потоке
160
        }
161
        else {
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) {
166
                        bound = ib;
167
                        break;
168
                    }
169

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];
174
                    break;
175
                }
176
        }
177

178
        if (!p_flow)
179
            return nullptr;
180

181
        size_t index = p_flow->flow_index + shift;
182

183
        if (index >= p_flow->code_flow.branches().size())
184
            return nullptr;
185

186
        return & p_flow->code_flow.branches()[index];
187
    }
188

189
    boundary_index_t Interpret::copyBaseBounds(const StackOfNames_interface & another_stack)
190
    {
191
        stack().startBoundary(BoundScope::Global, BOUNDARY_MARK_MODULE_FRAME);
192

193
        auto [begin, end] = another_stack.boundaryLowAndTop(0);
194

195
        for(name_index_t i=begin; i < end; ++i)
196
            stack().push(another_stack.variable(i).copyVariable());
197

198
        _stack.globals() = another_stack.globals();
199

200
        return stack().startBoundary(BoundScope::Global, BOUNDARY_MARK_MODULE_FRAME);
201
    }
202

203
    void Interpret::addFlowLayer_internal(const ast::Node & code,
204
                                boundary_index_t boundary_index, 
205
                                std::function<void (const FlowLayerInfo &)> on_layer_end)
206
    {
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}); // Например, метод без параметров
211
    }
212

213

214
}

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

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

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

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