loom

Форк
0
/
ModuleManagement.cpp 
261 строка · 9.5 Кб
1
/*
2
MIT License
3

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

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

9
#include "simodo/interpret/Interpret.h"
10
#include "simodo/module/ModuleManagement.h"
11
#include "simodo/module/CodeSupplier.h"
12
#include "simodo/module/HardModuleLoader.h"
13
#include "simodo/module/SoftModule.h"
14
#include "simodo/inout/convert/functions.h"
15
#include "simodo/bormental/DrBormental.h"
16
#include "simodo/inout/format/fmt.h"
17

18
#include <cassert>
19

20
#if __cplusplus >= __cpp_2017
21
#include <filesystem>
22
namespace fs = std::filesystem;
23
#else
24
#include <experimental/filesystem>
25
namespace fs = std::filesystem::experimental;
26
#endif
27

28
#include <boost/dll/import.hpp>
29

30
namespace dll = boost::dll;
31

32
#define CATCH_ERRORS
33

34
namespace simodo::module
35
{
36
    ModuleManagement::ModuleManagement( inout::Reporter_abstract & m, 
37
                         inout::InputStreamSupplier_interface & stream_supplier,
38
                         std::vector<std::string> interpret_places,
39
                         std::vector<std::string> hard_module_places,
40
                         std::vector<std::string> grammar_places,
41
                         interpret::InterpretType interpret_type,
42
                         interpret::SemanticDataCollector_interface & semantic_data,
43
                         std::ostream & tout,
44
                         std::string initial_contracts_file,
45
                         bool debug_mode,
46
                         uint64_t timeout,
47
                         bool resume,
48
                         bool need_full_debug_info,
49
                         const std::vector<interpret::BreakPoint> & breakpoints)
50
        : _m(m)
51
        , _stream_supplier(stream_supplier)
52
        , _semantics_places(interpret_places)
53
        , _hard_module_places(hard_module_places)
54
        , _grammar_places(grammar_places)
55
        , _interpret_type(interpret_type)
56
        , _semantic_data(semantic_data)
57
        , _tout(tout)
58
        , _initial_contracts_file(initial_contracts_file)
59
        , _debug_mode(debug_mode)
60
        , _timeout(timeout)
61
        , _resume(resume)
62
        , _need_full_debug_info(need_full_debug_info)
63
        , _breakpoints(breakpoints)
64
        , _loom(0, _debug_mode ? &_debug_condition : nullptr)
65
        , _hard_module_loader(hard_module_places)
66
    {
67
        _code_generator = std::make_unique<CodeSupplier>(_m,_grammar_places,_stream_supplier,_semantic_data);
68
        loadFactories();
69
    }
70

71
    void ModuleManagement::addSemanticFactories(std::vector<std::shared_ptr<interpret::SemanticModuleFactory_interface>> factories)
72
    {
73
        _semantic_factories.insert(_semantic_factories.end(),factories.begin(),factories.end());
74
    }
75

76
    bool ModuleManagement::execute(const std::string & module_name, std::vector<std::string> preload_module_names)
77
    {
78
        if (_semantic_factories.empty()) {
79
            _m.reportFatal({}, inout::fmt("Семантики не заданы"));
80
            return false;
81
        }
82

83
        interpret::Interpret inter(_interpret_type, _m, _loom, _semantic_factories, _debug_mode);
84
        bool                 ok = true;
85

86
        interpret::SemanticModules hosts;
87
        for(const std::shared_ptr<interpret::SemanticModuleFactory_interface> & f : _semantic_factories) {
88
            interpret::SemanticModule_interface * h = f->create(inter);
89
            if (h)
90
                hosts.push_back(h);
91
            else {
92
                ok = false;
93
                _m.reportFatal({}, inout::fmt("Не удалось создать семантику"));
94
                break;
95
            }
96
        }
97

98
        if (ok) {
99
            assert(&(inter.stack()));
100

101
            inter.stack().startBoundary(interpret::BoundScope::Global, interpret::BOUNDARY_MARK_MODULE_FRAME);
102

103
            for(const std::string & module_name : preload_module_names) {
104
                std::shared_ptr<variable::Module_interface> mod = _hard_module_loader.load(module_name, &inter);
105

106
                if(!mod) {
107
                    ok = false;
108
                    _m.reportFatal({}, inout::fmt("Не удалось загрузить модуль %1").arg(module_name));
109
                    break;
110
                }
111

112
                inter.stack().push({ inout::toU16(module_name), mod->instantiate(mod), inout::null_token_location,
113
                                    {{  {variable::SPEC_ORIGIN, variable::SPEC_ORIGIN_MODULE},
114
                                        {variable::SPEC_BUILTIN, true},
115
                                    }} });
116

117
                inter.stack().addGlobal(inter.stack().top());
118
            }
119
        }
120

121
        if (!ok) {
122
            for(interpret::SemanticModule_interface * h : hosts)
123
                delete h;
124
            return false;
125
        }
126

127
        inter.instantiateSemantics(hosts);
128
        inter.addBreakPoints(_breakpoints);
129

130
        if (!_initial_contracts_file.empty())
131
            ok = execute(inter, _initial_contracts_file);
132

133
        if (ok) {
134
            inter.stack().startBoundary(interpret::BoundScope::Global, interpret::BOUNDARY_MARK_MODULE_FRAME);
135

136
            ok = execute(inter, module_name);
137
        }
138

139
        _files = inter.files();
140
        _loom.finish();
141

142
        return ok;
143
    }
144

145
    bool ModuleManagement::isTheModuleLoaded(const std::string & module_name)
146
    {
147
        return _modules.find(module_name) != _modules.end();
148
    }
149

150
    const ast::Node * ModuleManagement::getCode(const std::string & module_name, const inout::uri_set_t & files)
151
    {
152
        _last_error = "";
153
        const ast::Node * node = _code_generator->getCode(module_name, files);
154

155
        if (node == nullptr && !_code_generator->last_error().empty())
156
            _last_error = _code_generator->last_error();
157
 
158
        return node;
159
    }
160

161
    std::shared_ptr<variable::Module_interface> ModuleManagement::registerSoftModule(const std::string & module_name, std::shared_ptr<variable::Object> module)
162
    {
163
        auto it = _modules.find(module_name);
164
        if (it != _modules.end())
165
            return std::shared_ptr<variable::Module_interface>();
166

167
        auto [it_new, ok] = _modules.insert({module_name, std::make_shared<SoftModule>(module)});
168
        if (!ok)
169
            return std::shared_ptr<variable::Module_interface>();
170

171
        return it_new->second;
172
    }
173

174
    std::shared_ptr<variable::Object> ModuleManagement::produceObject(const std::string & module_name,
175
                                interpret::Interpret_interface * interpret)
176
    {
177
        _last_error = "";
178
        auto it = _modules.find(module_name);
179

180
        if (it != _modules.end())
181
            return std::make_shared<variable::Object>(it->second->instantiate(it->second));
182

183
        std::shared_ptr<variable::Module_interface> module;
184
        fs::path                                    path_to_module {module_name};
185
        std::string                                 extension {path_to_module.extension().string()};
186

187
        if (extension.empty() || extension == ".") {
188
            HardModuleLoader hard_module_loader(_hard_module_places);
189

190
            module = hard_module_loader.load(module_name,interpret);
191

192
            if (!module)
193
                _last_error = hard_module_loader.last_error();
194
        }
195
        else {
196
            /// \note Загрузка мягких модулей выполняется в интерпретаторе, т.к. для
197
            /// этого необходимо использовать Interpret. Строго говоря, если мы попали сюда, 
198
            /// значит что-то пошло не так.
199
            assert(false);
200
        }
201

202
        if (!module)
203
            return std::shared_ptr<variable::Object>();
204

205
        version_t v = module->version();
206
        if (v.major() != LibVersion_Major || v.minor() > LibVersion_Minor) {
207
            _last_error = inout::fmt("Incorrect version of module '%1'").arg(module_name);
208
            return std::shared_ptr<variable::Object>();
209
        }
210

211
        _modules.insert({module_name, module});
212

213
        return std::make_shared<variable::Object>(module->instantiate(module));
214
    }
215

216
    void ModuleManagement::loadFactories()
217
    {
218
        for(const std::string & interpret_folder_name : _semantics_places) 
219
            if (!interpret_folder_name.empty()) {
220
                fs::path path_to_interpret_folder { interpret_folder_name };
221

222
                for (auto const & f : fs::directory_iterator{path_to_interpret_folder}) 
223
                    if (f.path().extension() == ".simodo-semantics") {
224
                        std::function<InterpretFactory_t> creator = nullptr;
225

226
#ifdef CATCH_ERRORS
227
                        try {
228
#endif
229
                            creator = dll::import_alias<InterpretFactory_t>(f.path().string().c_str(),"create_simodo_interpret");
230
#ifdef CATCH_ERRORS
231
                        }
232
                        catch(std::runtime_error & e) {
233
                            throw bormental::DrBormental("ModuleManagement::loadFactories", e.what());
234
                        }
235
#endif
236
                        _semantic_factories.push_back(creator(*this));
237
                    }
238
            }
239
    }
240

241
    bool ModuleManagement::execute(interpret::Interpret_interface & inter, const std::string & file_name)
242
    {
243
        inter.addFile(file_name);
244

245
        const ast::Node * code = getCode(file_name, inter.files());
246

247
        if (!code) {
248
            if (!_last_error.empty())
249
                _m.reportError(file_name, _last_error);
250
            return false;
251
        }
252

253
        if (!_debug_mode)
254
            return inter.execute(*code);
255

256
        inter.addFlowLayer(*code);
257
        _loom.stretch(inter.fiber());
258

259
        return debug(inter.files());
260
    }
261
}
262

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

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

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

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