loom

Форк
0
/
Interpret_Fiber.cpp 
196 строк · 7.1 Кб
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/bormental/DrBormental.h"
13
#include "simodo/inout/convert/functions.h"
14
#include "simodo/inout/format/fmt.h"
15

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

19
#define SemanticFiber_DEBUG_no
20

21
namespace simodo::interpret
22
{
23
    loom::FiberStatus Interpret::start()
24
    {
25
        InterpretState state = InterpretState::Flow;
26

27
        for(auto h : _hosts) {
28
            if (h->before_start() != InterpretState::Flow) {
29
                state = InterpretState::Complete;
30
            }
31
        }
32

33
        return state;
34
    }
35

36
    loom::FiberStatus Interpret::tieKnot()
37
    {
38
        _waiting_for = nullptr;
39
        assert(!_errors);
40

41
        if (_layer_stack.empty())
42
            return loom::FiberStatus::Complete;
43

44
        _layer_stack.back().index = flow().internal_work_index;
45

46
        assert(flow().index < flow().code.branches().size());
47

48
        _layer_stack.back().internal_work_index += 1;
49

50
        const ast::Node & node = flow().code.branches()[flow().index];
51

52
        if (checkBreakPoint(node))
53
            return loom::FiberStatus::Paused;
54

55
#ifndef SemanticFiber_DEBUG
56
        try
57
        {
58
#endif
59
            /// \todo Оптимизация на случай большого кол-ва семантических модулей :)
60
            /// В данном случае можно было бы упростить
61

62
            const std::u16string & current_host_name = node.host();
63

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)
67
                                { 
68
                                    return h->checkSemanticName(current_host_name);
69
                                });
70

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));
78
                }
79

80
                _last_host_name = current_host_name;
81
                _last_host      = *it_host;
82
            }
83

84
            _last_host->performOperation(node);
85

86
            while(true) {
87
                if (flow().internal_work_index < flow().code.branches().size())
88
                    break;
89
                    
90
                FlowLayerInfo flow_info = flow();
91

92
                _layer_stack.pop_back();
93

94
                if (flow_info.on_layer_end) {
95
                    /// \todo Нужно добавить обработку возвращаемого значения, чтобы можно было управлять выполнением
96
                    /// \todo Нужно убедиться, что в нештатных ситуациях, но при продолжении выполнения, вызов функции будет произведён
97
                    flow_info.on_layer_end(flow_info);
98
                }
99

100
                if (_layer_stack.empty())
101
                    break;
102
            }
103

104
#ifndef SemanticFiber_DEBUG
105
        }
106
        catch (const AnalyzeException & e)
107
        {
108
            _m.reportError(e.location(), e.what());
109
            _errors = true;
110
            return loom::FiberStatus::Complete;
111
        }
112
        catch (const bormental::DrBormental & e)
113
        {
114
            _m.reportError( node.token().makeLocation(files()),
115
                            inout::fmt("Произошло исключение в методе %1 при обработке оператора %2\nОписание исключения: %3")
116
                            .arg(e.where())
117
                            .arg(makeOperatorString(node))                        
118
                            .arg(e.what()));
119
            _errors = true;
120
            return _stop_by_error ? loom::FiberStatus::Paused : loom::FiberStatus::Complete;
121
        }
122
        catch (const std::exception & e)
123
        {
124
            _m.reportError( node.token().makeLocation(files()),
125
                            inout::fmt("Произошло исключение при обработке оператора %1\nОписание исключения: %2" )
126
                            .arg(makeOperatorString(node))
127
                            .arg(e.what()));
128
            _errors = true;
129
            return _stop_by_error ? loom::FiberStatus::Paused : loom::FiberStatus::Complete;
130
        }
131
        catch (...)
132
        {
133
            _m.reportError(node.token().makeLocation(files()),
134
                            inout::fmt("Произошло исключение при обработке оператора %1")
135
                            .arg(makeOperatorString(node)));
136
            _errors = true;
137
            return _stop_by_error ? loom::FiberStatus::Paused : loom::FiberStatus::Complete;
138
        }
139
#endif
140
        if (_waiting_for)
141
            return loom::FiberStatus::Delayed;
142

143
        return _layer_stack.empty() ? loom::FiberStatus::Complete : loom::FiberStatus::Flow;
144
    }
145

146
    void Interpret::finish()
147
    {
148
        for(auto h : _hosts) {
149
            if (h->before_finish(InterpretState::Flow) != InterpretState::Flow)
150
                _errors = true;
151
        }
152
    }
153

154
    bool Interpret::isReady() const
155
    {
156
        return !_layer_stack.empty();
157
    }
158

159
    const loom::Fiber_interface * Interpret::getWaitingFor()
160
    {
161
        return _waiting_for;
162
    }
163

164
    std::u16string Interpret::makeOperatorString(const ast::Node & operation_node)
165
    {
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"')";
169
    }
170

171
    bool Interpret::checkBreakPoint(const ast::Node & node)
172
    {
173
        /// \todo Нужно исключить повторные проверки для одной и той же строки (и файла), которые бывают часто
174

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

178
        if (uri_index >= _files.size())
179
            return false;
180

181
        const std::string & uri = _files[uri_index];
182

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;
186
                    });
187

188
        if (it == _breakpoints.end())
189
            return false;
190

191
        _breakpoints.erase(it);
192
            
193
        return true;
194
    }
195

196
}

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

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

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

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