1
#include "CommandExecutor.h"
3
#include "simodo/engine/FrameBody.h"
4
#include "simodo/inout/token/Tokenizer.h"
5
#include "simodo/inout/token/InputStream.h"
13
std::string getEngineStage(simodo::engine::Stage stage)
17
case simodo::engine::Stage::None:
19
case simodo::engine::Stage::Prepared:
21
case simodo::engine::Stage::Initialized:
23
case simodo::engine::Stage::Running:
25
case simodo::engine::Stage::Completed:
37
CommandExecutor::CommandExecutor(const Parameters & params)
45
engine::makeInitialContractFile(_params.loom_dir),
48
, _command_ready_mutex()
50
_out = std::make_unique<engine::RegularFormatter>(_engine);
53
int CommandExecutor::run()
55
if (!_engine.prepare()) {
56
std::cout << "Из-за предыдущих ошибок не удалось завести движок" << std::endl;
60
std::thread engine_runner_thread(&CommandExecutor::internal_runner, this);
62
inout::LexicalParameters lex;
64
lex.masks.push_back({ inout::BUILDING_NUMBER, inout::LexemeType::Number, 10 });
65
lex.markups.push_back({u"\"", u"\"", u"\\", inout::LexemeType::Annotation});
69
// Ждём, когда запуститься параллельная процедура internal_runner
71
std::this_thread::sleep_for(std::chrono::milliseconds(10));
76
if (!std::getline(std::cin,line))
82
std::istringstream str_in(line);
83
inout::InputStream in(str_in);
84
inout::Tokenizer tokenizer(0, in, lex);
86
std::vector<inout::Token> order;
87
inout::Token t = tokenizer.getToken();
89
while(t.type() != inout::LexemeType::Empty) {
91
t = tokenizer.getToken();
97
if (order[0].type() != inout::LexemeType::Id) {
98
_out->error("Wrong command");
102
std::u16string word = order[0].lexeme();
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();
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();
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();
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();
132
else if (word == u"w" || word == u"wait") {
136
std::unique_lock<std::mutex> locker(_engine_ready_mutex);
138
_engine_ready_condition.wait(locker, [this]{ return _engine_ready == true; });
142
else if (word == u"p" || word == u"pause") {
149
else if (word == u"fl" || word == u"files") {
154
else if (word == u"fb" || word == u"fibers") {
159
else if (word == u"ca" || word == u"calls") {
164
else if (word == u"lo" || word == u"locals") {
169
else if (word == u"h" || word == u"help") {
174
else if (word == u"q" || word == u"quit") {
176
_internal_quit_needed = true;
177
_command_ready_condition.notify_one();
181
_out->error("The command was not recognized");
190
engine_runner_thread.join();
195
/**************************************************************************
197
**************************************************************************/
199
void CommandExecutor::promptCommand()
201
if (_params.need_prompt_avoid)
204
std::cout << "simodo-debug (" << getEngineStage(_engine.stage())<< "): ";
208
void CommandExecutor::printHelp()
210
std::ostringstream out;
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
230
_engine.reporter().reportInformation(out.str());
233
void CommandExecutor::internal_runner()
235
_engine_ready = true;
238
std::unique_lock<std::mutex> locker(_command_ready_mutex);
240
_command_ready_condition.wait(locker, [this]{ return _internal_quit_needed || _internal_run_needed; });
242
if (_internal_quit_needed)
245
_internal_run_needed = false;
247
_engine.run(_internal_run_mode);
249
if (_params.need_engine_status_notification) {
250
if (_engine.stage() == engine::Stage::Completed)
258
_engine_ready = true;
259
_engine_ready_condition.notify_one();