loom

Форк
0
/
ModuleManagement.cpp 
193 строки · 7.0 Кб
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
35
{
36
    std::vector<std::string> makeSemanticsPlaces(const std::string & loom_dir)
37
    {
38
        fs::path path_to_loom_root(loom_dir);
39

40
        path_to_loom_root += "/bin/semantics";
41

42
        return {path_to_loom_root.lexically_normal().string()};
43
    }
44

45
    std::vector<std::string> makeHardModulePlaces(const std::string & loom_dir)
46
    {
47
        fs::path path_to_loom_root(loom_dir);
48

49
        path_to_loom_root += "/bin/modules";
50

51
        return {path_to_loom_root.lexically_normal().string()};
52
    }
53

54
    std::vector<std::string> makeGrammarsPlaces(const std::string & loom_dir)
55
    {
56
        fs::path path_to_loom_root(loom_dir);
57

58
        path_to_loom_root += "/data/grammar";
59

60
        return {path_to_loom_root.lexically_normal().string()};
61
    }
62

63
}
64

65
namespace simodo::module
66
{
67
    ModuleManagement::ModuleManagement( inout::Reporter_abstract & m, 
68
                        inout::InputStreamSupplier_interface & stream_supplier,
69
                        const std::string & simodo_root_path,
70
                        interpret::InterpretFactory_interface & interpret_factory,
71
                        interpret::SemanticDataCollector_interface & semantic_data_collector)
72
        : _m(m)
73
        , _stream_supplier(stream_supplier)
74
        , _simodo_root_path(simodo_root_path)
75
        , _interpret_factory(interpret_factory)
76
        , _semantic_data_collector(semantic_data_collector)
77
        , _hard_module_loader(makeHardModulePlaces(simodo_root_path))
78
    {
79
        _code_generator = std::make_unique<CodeSupplier>(_m, makeGrammarsPlaces(simodo_root_path), _stream_supplier,
80
                                                        _interpret_factory, _semantic_data_collector);
81
        loadSemanticModules();
82

83
        _interpret_factory.setSemanticFactories(semantic_factories());
84
    }
85

86
    std::shared_ptr<variable::Module_interface> ModuleManagement::loadHardModule(const std::string & module_name, 
87
                                    interpret::Interpret_interface * interpret)
88
    {
89
        return _hard_module_loader.load(module_name, interpret);
90
    }
91

92
    const ast::Node * ModuleManagement::getCode(const std::string & module_name, const inout::uri_set_t & files)
93
    {
94
        // _last_error = "";
95
        const ast::Node * node = _code_generator->getCode(module_name, files);
96
 
97
        return node;
98
    }
99

100
    bool ModuleManagement::isTheModuleLoaded(const std::string & module_name)
101
    {
102
        return _modules.find(module_name) != _modules.end();
103
    }
104

105
    std::shared_ptr<variable::Module_interface> ModuleManagement::registerSoftModule(const std::string & module_name, std::shared_ptr<variable::Object> module)
106
    {
107
        auto it = _modules.find(module_name);
108
        if (it != _modules.end())
109
            return std::shared_ptr<variable::Module_interface>();
110

111
        auto [it_new, ok] = _modules.insert({module_name, std::make_shared<SoftModule>(module)});
112
        if (!ok)
113
            return std::shared_ptr<variable::Module_interface>();
114

115
        return it_new->second;
116
    }
117

118
    std::shared_ptr<variable::Object> ModuleManagement::produceObject(const std::string & module_name,
119
                                interpret::Interpret_interface * interpret)
120
    {
121
        // _last_error = "";
122
        auto it = _modules.find(module_name);
123

124
        if (it != _modules.end())
125
            return it->second->instantiate(it->second).getObject();
126

127
        std::shared_ptr<variable::Module_interface> module;
128
        fs::path                                    path_to_module {module_name};
129
        std::string                                 extension {path_to_module.extension().string()};
130

131
        if (extension.empty() || extension == ".") {
132
            HardModuleLoader hard_module_loader(makeHardModulePlaces(_simodo_root_path));
133

134
            module = hard_module_loader.load(module_name,interpret);
135

136
            if (!module) {
137
                // _last_error = hard_module_loader.last_error();
138
                _m.reportFatal(hard_module_loader.last_error());
139
            }
140
        }
141
        else {
142
            /// \note Загрузка мягких модулей выполняется в интерпретаторе, т.к. для
143
            /// этого необходимо использовать Interpret. Строго говоря, если мы попали сюда, 
144
            /// значит что-то пошло не так.
145
            assert(false);
146
        }
147

148
        if (!module)
149
            return std::shared_ptr<variable::Object>();
150

151
        version_t v = module->version();
152
        if (v.major() != LibVersion_Major || v.minor() > LibVersion_Minor) {
153
            // _last_error = inout::fmt("Incorrect version of module '%1'").arg(module_name);
154
            _m.reportFatal(inout::fmt("Incorrect version of module '%1'").arg(module_name));
155
            return std::shared_ptr<variable::Object>();
156
        }
157

158
        _modules.insert({module_name, module});
159

160
        /// \todo Пересмотреть странную передачу самого себя в свой же метод.
161
        /// PVS Studio: warn V678 An object is used as an argument to its own method.
162
        /// Consider checking the first actual argument of the 'instantiate' function.
163
        return module->instantiate(module).getObject();
164
    }
165

166
    void ModuleManagement::loadSemanticModules()
167
    {
168
        std::vector<std::string> semantics_places = makeSemanticsPlaces(_simodo_root_path);
169

170
        for(const std::string & interpret_folder_name : semantics_places) 
171
            if (!interpret_folder_name.empty()) {
172
                fs::path path_to_interpret_folder { interpret_folder_name };
173

174
                for (auto const & f : fs::directory_iterator{path_to_interpret_folder}) 
175
                    if (f.path().extension() == ".simodo-semantics") {
176
                        std::function<InterpretFactory_t> creator = nullptr;
177

178
#ifdef CATCH_ERRORS
179
                        try {
180
#endif
181
                            creator = dll::import_alias<InterpretFactory_t>(f.path().string().c_str(),"create_simodo_interpret");
182
#ifdef CATCH_ERRORS
183
                        }
184
                        catch(std::runtime_error & e) {
185
                            throw bormental::DrBormental("ModuleManagement::loadSemanticModules", e.what());
186
                        }
187
#endif
188
                        _semantic_factories.push_back(creator(*this));
189
                    }
190
            }
191
    }
192

193
}
194

195

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

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

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

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