loom

Форк
0
/
RegularFormatter.cpp 
349 строк · 12.0 Кб
1
/*
2
MIT License
3

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

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

9
#include "simodo/engine/debug/RegularFormatter.h"
10
#include "simodo/inout/convert/functions.h"
11
#include "simodo/inout/format/fmt.h"
12

13
#include <cstdio>
14
#include <iomanip>
15
#include <sstream>
16
#include <algorithm>
17

18
namespace simodo::engine
19
{
20
    RegularFormatter::RegularFormatter(const engine::Engine_interface & engine)
21
        : _engine(engine)
22
    {
23
    }
24

25
    void RegularFormatter::error(const std::string & msg) const
26
    {
27
        _engine.reporter().reportInformation("* error: " + msg);
28
    }
29

30
    bool RegularFormatter::source(const inout::TokenLocation & location) const
31
    {
32
        inout::uri_index_t  uri  = location.uri_index();
33
        inout::uri_set_t    uris = _engine.interpret().files();
34

35
        if (uri >= uris.size()) {
36
            error("Overflow of the uri index");
37
            return false;
38
        }
39

40
        _engine.reporter().reportInformation("Source: " + uris[uri]);
41

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]);
46

47
        if (!file) {
48
            error("Wrong input source");
49
            return false;
50
        }
51

52
        inout::position_line_t point_line = location.range().start().line();
53
        inout::position_line_t first_line = point_line;
54

55
        while(first_line != 0 && point_line - first_line < 2)
56
            first_line --;
57

58
        inout::position_line_t last_line = point_line + 2;
59
        inout::position_line_t line      = 0;
60

61
        int digits = 2;
62
        int max = std::max(1, int(last_line+1));
63
        while (max >= 10) {
64
            max /= 10;
65
            ++digits;
66
        }
67

68
        std::ostringstream out;
69

70
        if (!file->eof()) {
71
            if (line >= first_line)
72
                out << "[" << std::setw(digits) << line + 1 << "]";
73
        }
74
        while(!file->eof()) {
75
            char16_t ch = file->get();
76
            if (line >= first_line) {
77
                std::u16string s16;
78
                s16 += ch;
79
                out << inout::toU8(s16);
80
            }
81
            if (ch == u'\n') {
82
                if (line == point_line) {
83
                    /// \todo Вычисление длины пропуска выполняется буз учёта табуляций.
84
                    /// Желательно учесть табуляции
85
                    int space = location.range().start().character() + digits + 3;
86
                    out << std::setw(space) << '^' << std::endl;
87
                }
88
                line ++;
89
                if (line > last_line)
90
                    break;
91
                if (line >= first_line)
92
                    out << "[" << std::setw(digits) << line + 1 << "]";
93
            }
94
        }
95

96
        _engine.reporter().reportInformation(out.str());
97
        return true;
98
    }
99

100
    bool RegularFormatter::fibers() const
101
    {
102
        std::vector<loom::FiberStructure> fiber_set = _engine.fibers();
103

104
        if (fiber_set.empty()) {
105
            error("The fiber set is empty");
106
            return false;
107
        }
108

109
        std::ostringstream out;
110

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)" << ' '
121
            << "error? causer?"
122
            << std::endl;
123

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") << ' ';
133

134
            if (fs.status == loom::FiberStatus::Flow) {
135
                out << "(*)" << std::endl;
136
                continue;
137
            }
138

139
            interpret::Interpret_interface * 
140
                    p_interpret = dynamic_cast<interpret::Interpret_interface *>(fs.p_fiber);
141

142
            if (!p_interpret) {
143
                out << "?" << std::endl;
144
                continue;
145
            }
146

147
            out << getInfo(p_interpret->lookupOperationNode())
148
                << (p_interpret->errors() ? " yes" : "")
149
                << (fs.p_fiber == _engine.causer() ? " yes" : "")
150
                << std::endl;
151
        }
152

153
        _engine.reporter().reportInformation(out.str());
154
        return true;
155
    }
156

157
    bool RegularFormatter::calls(const interpret::Interpret_interface * interpret, bool with_locals) const
158
    {
159
        if (!interpret) {
160
            interpret = getCauser();
161
            if (!interpret) {
162
                error("It is impossible to determine the interpreter fiber");
163
                return false;
164
            }
165
        }
166

167
        _engine.reporter().reportInformation("Calls:");
168

169
        std::vector<interpret::boundary_index_t> frames = interpret->stack().getFunctionBounds();
170

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);
178
            std::string text;
179

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();
184

185
                text += std::to_string(i) + ". ";
186

187
                text += "\tfn " + inout::toU8(function_variable.origin().name())
188
                      + "(";
189
                for(size_t i=0; i < declarations.size(); ++i) {
190
                    if (i > 0)
191
                        text += ", ";
192

193
                    text += variable::getValueTypeName(declarations[i].type());
194

195
                    if (!declarations[i].name().empty())
196
                        text += " " + inout::toU8(declarations[i].name());
197
                }
198
                text += ")";
199
                if (return_type.type() != variable::ValueType::Null)
200
                    text += " -> " + variable::getValueTypeName(return_type.type());
201
            }
202
            else
203
                text += "\t<root module>";
204

205
            _engine.reporter().reportInformation(text);
206

207
            const ast::Node * p_node = interpret->lookupOperationNode(0,frames[i]);
208

209
            if (p_node)
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);
215
            }
216
            else
217
                text = inout::fmt("\tCall point is out");
218

219
            _engine.reporter().reportInformation(text);
220
            text = {};
221

222
            if (with_locals)
223
                locals(interpret, i);
224
        }
225

226
        return true;
227
    }
228

229
    bool RegularFormatter::locals(const interpret::Interpret_interface * interpret, size_t call_depth) const
230
    {
231
        if (!interpret) {
232
            interpret = getCauser();
233
            if (!interpret) {
234
                error("It is impossible to determine the interpreter fiber");
235
                return false;
236
            }
237
        }
238

239
        std::vector<interpret::boundary_index_t> frames = interpret->stack().getFunctionBounds();
240

241
        if (frames.empty()) {
242
            error("The call stack is empty");
243
            return false;
244
        }
245

246
        if (call_depth >= frames.size()) {
247
            error("The specified depth of the call stack exceeds its size");
248
            return false;
249
        }
250

251
        std::vector<interpret::name_index_t> locals = interpret->stack().getFrameLocals(frames[call_depth]);
252
        std::ostringstream                   out;
253

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);
258

259
                out << "\t\t" + inout::toU8(v.origin().name()) 
260
                    << " = " << inout::toU8(variable::toString(v.origin().value())) << std::endl;
261
            }
262
        }
263

264
        _engine.reporter().reportInformation(out.str());
265
        return true;
266
    }
267

268
    bool RegularFormatter::files() const
269
    {
270
        inout::uri_set_t uris = _engine.interpret().files();
271

272
        if (uris.empty()) {
273
            error("The uri set is empty");
274
            return false;
275
        }
276

277
        std::ostringstream out;
278

279
        for(size_t i=0; i < uris.size(); ++i)
280
            out << std::setw(6) << i << ": " << uris[i] << std::endl;
281

282
        _engine.reporter().reportInformation(out.str());
283
        return true;
284
    }
285

286
    bool RegularFormatter::stoped() const
287
    {
288
        _engine.reporter().reportInformation("The work is stopped");
289
        return true;
290
    }
291

292
    bool RegularFormatter::paused() const
293
    {
294
        _engine.reporter().reportInformation("The work is paused");
295
        return true;
296
    }
297

298
    bool RegularFormatter::quit() const
299
    {
300
        _engine.reporter().reportInformation("The work is completed");
301
        return true;
302
    }
303

304
    // protected ----------------------------------------------------------------------------------------
305

306
    const interpret::Interpret_interface * RegularFormatter::getCauser() const
307
    {
308
        return dynamic_cast<const interpret::Interpret_interface *>(_engine.causer());
309
    }
310

311
    std::string RegularFormatter::getInfo(const ast::Node * p) const
312
    {
313
        std::string info;
314

315
        if (p)
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()));
320
        else
321
            info = "-";
322

323
        return "(" + info + ")";
324
    }
325

326
    std::string RegularFormatter::getFiberName(const loom::FiberStructure & fs) const
327
    {
328
        if (fs.name.empty())
329
            return std::to_string(int(fs.no));
330

331
        return fs.name + "/" + std::to_string(int(fs.no));
332
    }
333

334
    const loom::FiberStructure &RegularFormatter::findFiberStructure(const std::vector<loom::FiberStructure> & fibers, const loom::Fiber_interface * p_fiber) const
335
    {
336
        static const loom::FiberStructure none {nullptr,nullptr,false,loom::FiberStatus::Complete,0,{}};
337

338
        auto const it = std::find_if(fibers.begin(), fibers.end(), [p_fiber](const loom::FiberStructure & fs){
339
                        return fs.p_fiber == p_fiber;                        
340
                    });
341

342
        if (it == fibers.end())
343
            return none;
344

345
        return *it;
346
    }
347

348

349
}
350

351

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

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

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

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