4
Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
6
https://bmstu.codes/lsx/simodo/loom
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"
20
#if __cplusplus >= __cpp_2017
22
namespace fs = std::filesystem;
24
#include <experimental/filesystem>
25
namespace fs = std::filesystem::experimental;
28
#include <boost/dll/import.hpp>
30
namespace dll = boost::dll;
34
namespace simodo::module
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,
44
std::string initial_contracts_file,
48
bool need_full_debug_info,
49
const std::vector<interpret::BreakPoint> & breakpoints)
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)
58
, _initial_contracts_file(initial_contracts_file)
59
, _debug_mode(debug_mode)
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)
67
_code_generator = std::make_unique<CodeSupplier>(_m,_grammar_places,_stream_supplier,_semantic_data);
71
void ModuleManagement::addSemanticFactories(std::vector<std::shared_ptr<interpret::SemanticModuleFactory_interface>> factories)
73
_semantic_factories.insert(_semantic_factories.end(),factories.begin(),factories.end());
76
bool ModuleManagement::execute(const std::string & module_name, std::vector<std::string> preload_module_names)
78
if (_semantic_factories.empty()) {
79
_m.reportFatal({}, inout::fmt("Семантики не заданы"));
83
interpret::Interpret inter(_interpret_type, _m, _loom, _semantic_factories, _debug_mode);
86
interpret::SemanticModules hosts;
87
for(const std::shared_ptr<interpret::SemanticModuleFactory_interface> & f : _semantic_factories) {
88
interpret::SemanticModule_interface * h = f->create(inter);
93
_m.reportFatal({}, inout::fmt("Не удалось создать семантику"));
99
assert(&(inter.stack()));
101
inter.stack().startBoundary(interpret::BoundScope::Global, interpret::BOUNDARY_MARK_MODULE_FRAME);
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);
108
_m.reportFatal({}, inout::fmt("Не удалось загрузить модуль %1").arg(module_name));
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},
117
inter.stack().addGlobal(inter.stack().top());
122
for(interpret::SemanticModule_interface * h : hosts)
127
inter.instantiateSemantics(hosts);
128
inter.addBreakPoints(_breakpoints);
130
if (!_initial_contracts_file.empty())
131
ok = execute(inter, _initial_contracts_file);
134
inter.stack().startBoundary(interpret::BoundScope::Global, interpret::BOUNDARY_MARK_MODULE_FRAME);
136
ok = execute(inter, module_name);
139
_files = inter.files();
145
bool ModuleManagement::isTheModuleLoaded(const std::string & module_name)
147
return _modules.find(module_name) != _modules.end();
150
const ast::Node * ModuleManagement::getCode(const std::string & module_name, const inout::uri_set_t & files)
153
const ast::Node * node = _code_generator->getCode(module_name, files);
155
if (node == nullptr && !_code_generator->last_error().empty())
156
_last_error = _code_generator->last_error();
161
std::shared_ptr<variable::Module_interface> ModuleManagement::registerSoftModule(const std::string & module_name, std::shared_ptr<variable::Object> module)
163
auto it = _modules.find(module_name);
164
if (it != _modules.end())
165
return std::shared_ptr<variable::Module_interface>();
167
auto [it_new, ok] = _modules.insert({module_name, std::make_shared<SoftModule>(module)});
169
return std::shared_ptr<variable::Module_interface>();
171
return it_new->second;
174
std::shared_ptr<variable::Object> ModuleManagement::produceObject(const std::string & module_name,
175
interpret::Interpret_interface * interpret)
178
auto it = _modules.find(module_name);
180
if (it != _modules.end())
181
return std::make_shared<variable::Object>(it->second->instantiate(it->second));
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()};
187
if (extension.empty() || extension == ".") {
188
HardModuleLoader hard_module_loader(_hard_module_places);
190
module = hard_module_loader.load(module_name,interpret);
193
_last_error = hard_module_loader.last_error();
196
/// \note Загрузка мягких модулей выполняется в интерпретаторе, т.к. для
197
/// этого необходимо использовать Interpret. Строго говоря, если мы попали сюда,
198
/// значит что-то пошло не так.
203
return std::shared_ptr<variable::Object>();
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>();
211
_modules.insert({module_name, module});
213
return std::make_shared<variable::Object>(module->instantiate(module));
216
void ModuleManagement::loadFactories()
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 };
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;
229
creator = dll::import_alias<InterpretFactory_t>(f.path().string().c_str(),"create_simodo_interpret");
232
catch(std::runtime_error & e) {
233
throw bormental::DrBormental("ModuleManagement::loadFactories", e.what());
236
_semantic_factories.push_back(creator(*this));
241
bool ModuleManagement::execute(interpret::Interpret_interface & inter, const std::string & file_name)
243
inter.addFile(file_name);
245
const ast::Node * code = getCode(file_name, inter.files());
248
if (!_last_error.empty())
249
_m.reportError(file_name, _last_error);
254
return inter.execute(*code);
256
inter.addFlowLayer(*code);
257
_loom.stretch(inter.fiber());
259
return debug(inter.files());