4
Copyright (c) 2024 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
6
https://bmstu.codes/lsx/simodo/loom
9
#include "simodo/engine/debug/RegularFormatter.h"
10
#include "simodo/inout/convert/functions.h"
11
#include "simodo/inout/format/fmt.h"
18
namespace simodo::engine
20
RegularFormatter::RegularFormatter(const engine::Engine_interface & engine)
25
void RegularFormatter::error(const std::string & msg) const
27
_engine.reporter().reportInformation("* error: " + msg);
30
bool RegularFormatter::source(const inout::TokenLocation & location) const
32
inout::uri_index_t uri = location.uri_index();
33
inout::uri_set_t uris = _engine.interpret().files();
35
if (uri >= uris.size()) {
36
error("Overflow of the uri index");
40
_engine.reporter().reportInformation("Source: " + uris[uri]);
42
const inout::InputStreamSupplier_interface &
43
input_supplier = _engine.input_stream_supplier();
44
std::shared_ptr<inout::InputStream_interface>
45
file = input_supplier.supply(uris[uri]);
48
error("Wrong input source");
52
inout::position_line_t point_line = location.range().start().line();
53
inout::position_line_t first_line = point_line;
55
while(first_line != 0 && point_line - first_line < 2)
58
inout::position_line_t last_line = point_line + 2;
59
inout::position_line_t line = 0;
62
int max = std::max(1, int(last_line+1));
68
std::ostringstream out;
71
if (line >= first_line)
72
out << "[" << std::setw(digits) << line + 1 << "]";
75
char16_t ch = file->get();
76
if (line >= first_line) {
79
out << inout::toU8(s16);
82
if (line == point_line) {
83
/// \todo Вычисление длины пропуска выполняется буз учёта табуляций.
84
/// Желательно учесть табуляции
85
int space = location.range().start().character() + digits + 3;
86
out << std::setw(space) << '^' << std::endl;
91
if (line >= first_line)
92
out << "[" << std::setw(digits) << line + 1 << "]";
96
_engine.reporter().reportInformation(out.str());
100
bool RegularFormatter::fibers() const
102
std::vector<loom::FiberStructure> fiber_set = _engine.fibers();
104
if (fiber_set.empty()) {
105
error("The fiber set is empty");
109
std::ostringstream out;
111
out << "Fibers:" << std::endl;
112
out << std::setfill('.')
113
<< std::setw(6) << std::right << "No" << ' '
114
<< std::setw(14) << std::left << "Name" << ' '
115
<< std::setw(14) << std::right << "Address" << ' '
116
<< std::setw(14) << std::right << "Parent" << ' '
117
<< std::setw(14) << std::right << "Waiting for" << ' '
118
<< std::setw(8) << std::left << "Status" << ' '
119
<< std::setw(10) << std::left << "delete?" << ' '
120
<< "(file,line,host,op)" << ' '
124
for(auto & fs : fiber_set) {
125
out << std::setfill(' ')
126
<< std::setw(6) << std::right << fs.no << ' '
127
<< std::setw(14) << std::left << fs.name << ' '
128
<< std::setw(14) << std::right << std::hex << fs.p_fiber << ' '
129
<< std::setw(14) << std::right << std::hex << fs.p_parent << ' '
130
<< std::setw(14) << std::right << std::hex << fs.p_waiting_for << ' '
131
<< std::setw(8) << std::left << loom::getFiberStatusName(fs.status) << ' '
132
<< std::setw(10) << std::left << (fs.need_delete ? "yes" : "no") << ' ';
134
if (fs.status == loom::FiberStatus::Flow) {
135
out << "(*)" << std::endl;
139
interpret::Interpret_interface *
140
p_interpret = dynamic_cast<interpret::Interpret_interface *>(fs.p_fiber);
143
out << "?" << std::endl;
147
out << getInfo(p_interpret->lookupOperationNode())
148
<< (p_interpret->errors() ? " yes" : "")
149
<< (fs.p_fiber == _engine.causer() ? " yes" : "")
153
_engine.reporter().reportInformation(out.str());
157
bool RegularFormatter::calls(const interpret::Interpret_interface * interpret, bool with_locals) const
160
interpret = getCauser();
162
error("It is impossible to determine the interpreter fiber");
167
_engine.reporter().reportInformation("Calls:");
169
std::vector<interpret::boundary_index_t> frames = interpret->stack().getFunctionBounds();
171
for(size_t i=0; i < frames.size(); ++i) {
172
interpret::boundary_index_t fi = frames[i];
173
auto [begin, end] = interpret->stack().boundaryLowAndTop(fi);
174
interpret::name_index_t function_index = begin - 1;
175
const variable::Variable function_variable = function_index >= interpret->stack().index_over_top()
176
? variable::error_variable()
177
: interpret->stack().variable(function_index);
180
if (function_variable.origin().value().isFunction()) {
181
variable::FunctionWrapper function(function_variable);
182
const variable::Variable & return_type = function.getReturnDeclarationVariable();
183
variable::VariableSetWrapper declarations = function.getArgumentDeclarationVariables();
185
text += std::to_string(i) + ". ";
187
text += "\tfn " + inout::toU8(function_variable.origin().name())
189
for(size_t i=0; i < declarations.size(); ++i) {
193
text += variable::getValueTypeName(declarations[i].type());
195
if (!declarations[i].name().empty())
196
text += " " + inout::toU8(declarations[i].name());
199
if (return_type.type() != variable::ValueType::Null)
200
text += " -> " + variable::getValueTypeName(return_type.type());
203
text += "\t<root module>";
205
_engine.reporter().reportInformation(text);
207
const ast::Node * p_node = interpret->lookupOperationNode(0,frames[i]);
210
text = inout::fmt("\tCalled from %1:").arg(getInfo(p_node));
211
else if (function_variable.type() == variable::ValueType::Ref) {
212
text = inout::fmt("\tCall point is out, formal call location: (f:%1, l:%2):")
213
.arg(function_variable.location().uri_index())
214
.arg(function_variable.location().range().start().line()+1);
217
text = inout::fmt("\tCall point is out");
219
_engine.reporter().reportInformation(text);
223
locals(interpret, i);
229
bool RegularFormatter::locals(const interpret::Interpret_interface * interpret, size_t call_depth) const
232
interpret = getCauser();
234
error("It is impossible to determine the interpreter fiber");
239
std::vector<interpret::boundary_index_t> frames = interpret->stack().getFunctionBounds();
241
if (frames.empty()) {
242
error("The call stack is empty");
246
if (call_depth >= frames.size()) {
247
error("The specified depth of the call stack exceeds its size");
251
std::vector<interpret::name_index_t> locals = interpret->stack().getFrameLocals(frames[call_depth]);
252
std::ostringstream out;
254
if (locals.size() > 0) {
255
out << inout::fmt("\tLocals:").str() << std::endl;
256
for(interpret::name_index_t i : locals) {
257
const variable::Variable & v = interpret->stack().variable(i);
259
out << "\t\t" + inout::toU8(v.origin().name())
260
<< " = " << inout::toU8(variable::toString(v.origin().value())) << std::endl;
264
_engine.reporter().reportInformation(out.str());
268
bool RegularFormatter::files() const
270
inout::uri_set_t uris = _engine.interpret().files();
273
error("The uri set is empty");
277
std::ostringstream out;
279
for(size_t i=0; i < uris.size(); ++i)
280
out << std::setw(6) << i << ": " << uris[i] << std::endl;
282
_engine.reporter().reportInformation(out.str());
286
bool RegularFormatter::stoped() const
288
_engine.reporter().reportInformation("The work is stopped");
292
bool RegularFormatter::paused() const
294
_engine.reporter().reportInformation("The work is paused");
298
bool RegularFormatter::quit() const
300
_engine.reporter().reportInformation("The work is completed");
304
// protected ----------------------------------------------------------------------------------------
306
const interpret::Interpret_interface * RegularFormatter::getCauser() const
308
return dynamic_cast<const interpret::Interpret_interface *>(_engine.causer());
311
std::string RegularFormatter::getInfo(const ast::Node * p) const
316
info = "f:" + std::to_string(int(p->token().location().uri_index())) + ", "
317
+ "l:" + std::to_string(p->token().location().range().start().line()+1) + ", "
318
+ "h:" + inout::toU8(p->host()) + ", "
319
+ "o:" + std::to_string(int(p->operation()));
323
return "(" + info + ")";
326
std::string RegularFormatter::getFiberName(const loom::FiberStructure & fs) const
329
return std::to_string(int(fs.no));
331
return fs.name + "/" + std::to_string(int(fs.no));
334
const loom::FiberStructure &RegularFormatter::findFiberStructure(const std::vector<loom::FiberStructure> & fibers, const loom::Fiber_interface * p_fiber) const
336
static const loom::FiberStructure none {nullptr,nullptr,false,loom::FiberStatus::Complete,0,{}};
338
auto const it = std::find_if(fibers.begin(), fibers.end(), [p_fiber](const loom::FiberStructure & fs){
339
return fs.p_fiber == p_fiber;
342
if (it == fibers.end())