loom

Форк
0
/
CommandExecutor.cpp 
263 строки · 8.8 Кб
1
#include "CommandExecutor.h"
2

3
#include "simodo/engine/FrameBody.h"
4
#include "simodo/inout/token/Tokenizer.h"
5
#include "simodo/inout/token/InputStream.h"
6

7
#include <thread>
8
#include <iostream>
9
#include <sstream>
10

11
namespace 
12
{
13
    std::string getEngineStage(simodo::engine::Stage stage)
14
    {
15
        switch (stage)
16
        {
17
        case simodo::engine::Stage::None:
18
            return "none";        
19
        case simodo::engine::Stage::Prepared:
20
            return "prepared";        
21
        case simodo::engine::Stage::Initialized:
22
            return "initalized";        
23
        case simodo::engine::Stage::Running:
24
            return "running";        
25
        case simodo::engine::Stage::Completed:
26
            return "completed";        
27
        default:
28
            break;
29
        }
30

31
        return "?";
32
    }
33
}
34

35
namespace simodo 
36
{
37
    CommandExecutor::CommandExecutor(const Parameters & params)
38
        : _params(params)
39
        , _reporter()
40
        , _source_supplier()
41
        , _engine(
42
                _reporter, 
43
                _source_supplier, 
44
                _params.loom_dir, 
45
                engine::makeInitialContractFile(_params.loom_dir), 
46
                _params.file_name,
47
                _logistics)
48
        , _command_ready_mutex()
49
    {
50
        _out = std::make_unique<engine::RegularFormatter>(_engine);
51
    }
52

53
    int CommandExecutor::run()
54
    {
55
        if (!_engine.prepare()) {
56
            std::cout << "Из-за предыдущих ошибок не удалось завести движок" << std::endl;
57
            return 1;
58
        }
59

60
        std::thread engine_runner_thread(&CommandExecutor::internal_runner, this);
61

62
        inout::LexicalParameters lex;
63

64
        lex.masks.push_back({ inout::BUILDING_NUMBER, inout::LexemeType::Number, 10 });
65
        lex.markups.push_back({u"\"", u"\"", u"\\", inout::LexemeType::Annotation});
66

67
        promptCommand();
68

69
        // Ждём, когда запуститься параллельная процедура internal_runner
70
        while(!_engine_ready)
71
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
72

73
        while(true) {
74
            std::string line;
75
        
76
            if (!std::getline(std::cin,line))
77
                break;
78

79
            if (line.empty())
80
                continue;
81

82
            std::istringstream        str_in(line);
83
            inout::InputStream        in(str_in);
84
            inout::Tokenizer          tokenizer(0, in, lex);
85

86
            std::vector<inout::Token> order;
87
            inout::Token              t = tokenizer.getToken();
88

89
            while(t.type() != inout::LexemeType::Empty) {
90
                order.push_back(t);
91
                t = tokenizer.getToken();
92
            }
93

94
            if (order.empty())
95
                continue;
96

97
            if (order[0].type() != inout::LexemeType::Id) {
98
                _out->error("Wrong command");
99
                continue;
100
            }
101

102
            std::u16string word = order[0].lexeme();
103

104
            if (word == u"r" || word == u"run") {
105
                _internal_run_needed = true;
106
                _internal_run_mode = interpret::NextStepBehaviour::Run;
107
                _engine_ready = false;
108
                _command_ready_condition.notify_one();
109
                continue;
110
            }
111
            else if (word == u"s" || word == u"step") {
112
                _internal_run_needed = true;
113
                _internal_run_mode = interpret::NextStepBehaviour::Step;
114
                _engine_ready = false;
115
                _command_ready_condition.notify_one();
116
                continue;
117
            }
118
            else if (word == u"i" || word == u"in") {
119
                _internal_run_needed = true;
120
                _internal_run_mode = interpret::NextStepBehaviour::In;
121
                _engine_ready = false;
122
                _command_ready_condition.notify_one();
123
                continue;
124
            }
125
            else if (word == u"o" || word == u"out") {
126
                _internal_run_needed = true;
127
                _internal_run_mode = interpret::NextStepBehaviour::Out;
128
                _engine_ready = false;
129
                _command_ready_condition.notify_one();
130
                continue;
131
            }
132
            else if (word == u"w" || word == u"wait") {
133
                if (_engine_ready)
134
                    promptCommand();
135
                else {
136
                    std::unique_lock<std::mutex> locker(_engine_ready_mutex);
137

138
                    _engine_ready_condition.wait(locker, [this]{ return _engine_ready == true; });
139
                }
140
                continue;
141
            }
142
            else if (word == u"p" || word == u"pause") {
143
                if (_engine.busy())
144
                    _engine.pause();
145
                else
146
                    promptCommand();
147
                continue;
148
            }
149
            else if (word == u"fl" || word == u"files") {
150
                _out->files();
151
                promptCommand();
152
                continue;
153
            }
154
            else if (word == u"fb" || word == u"fibers") {
155
                _out->fibers();
156
                promptCommand();
157
                continue;
158
            }
159
            else if (word == u"ca" || word == u"calls") {
160
                _out->calls();
161
                promptCommand();
162
                continue;
163
            }
164
            else if (word == u"lo" || word == u"locals") {
165
                _out->locals();
166
                promptCommand();
167
                continue;
168
            }
169
            else if (word == u"h" || word == u"help") {
170
                printHelp();
171
                promptCommand();
172
                continue;
173
            }
174
            else if (word == u"q" || word == u"quit") {
175
                _engine.cancel();
176
                _internal_quit_needed = true;
177
                _command_ready_condition.notify_one();
178
                break;
179
            }
180
            else {
181
                _out->error("The command was not recognized");
182
                printHelp();
183
                promptCommand();
184
                continue;
185
            }
186
        }
187

188
        _out->quit();
189

190
        engine_runner_thread.join();
191

192
        return 0;
193
    }
194

195
    /**************************************************************************
196
     * private
197
     **************************************************************************/
198

199
    void CommandExecutor::promptCommand()
200
    {
201
        if (_params.need_prompt_avoid)
202
            return;
203

204
        std::cout << "simodo-debug (" << getEngineStage(_engine.stage())<< "): ";
205
        std::cout.flush();
206
    }
207

208
    void CommandExecutor::printHelp()
209
    {
210
        std::ostringstream out;
211

212
        out << "Debugger commands:" << std::endl
213
            << "r | run                      - Run interpretation" << std::endl
214
            << "s | step                     - Produce a step to next executable line" << std::endl
215
            << "i | in                       - Produce a step into next calling executable" << std::endl
216
            << "                               (function or soft module constructor) line" << std::endl
217
            << "o | out                      - Produce a step out of executed calling" << std::endl
218
            << "w | wait                     - Wait for the interpretation to be completed" << std::endl
219
            << "                               (required for automatic tests)" << std::endl
220
            << "p | pause                    - Suspend execution" << std::endl
221
            << "fl | files                   - Show the loaded files by internal numbers" << std::endl
222
            << "fb | fibers                  - Show the actual fibers info" << std::endl
223
            << "ca | calls [<fiber_no>] [lo] - Show the call stack for a given fiber [or causer]" << std::endl
224
            << "lo | locals [<fiber_no>] [<frame_no>] - Show the local declared variables for a" << std::endl
225
            << "                               given fiber [or causer] and frame [or top]" << std::endl
226
            << "h | help                     - Show the commands list" << std::endl
227
            << "q | quit                     - Quit the debugger" << std::endl
228
            ;
229

230
        _engine.reporter().reportInformation(out.str());
231
    }
232
    
233
    void CommandExecutor::internal_runner()
234
    {
235
        _engine_ready = true;
236

237
        while(true) {
238
            std::unique_lock<std::mutex> locker(_command_ready_mutex);
239

240
            _command_ready_condition.wait(locker, [this]{ return _internal_quit_needed || _internal_run_needed; });
241

242
            if (_internal_quit_needed)
243
                break;
244

245
            _internal_run_needed = false;
246

247
            _engine.run(_internal_run_mode);
248

249
            if (_params.need_engine_status_notification) {
250
                if (_engine.stage() == engine::Stage::Completed)
251
                    _out->stoped();
252
                else
253
                    _out->paused();
254
            }
255

256
            promptCommand();
257

258
            _engine_ready = true;
259
            _engine_ready_condition.notify_one();
260
        }
261
    }
262

263
}
264

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

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

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

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