15 if (!fs::exists(path)) {
16 driver_.WLOG(
"import path '{}' does not exist", path.string());
17 return {
nullptr,
false};
20 const fs::path* imported_path =
nullptr;
22 for (
const auto& parsed_path : parsed_paths_) {
23 if (fs::equivalent(parsed_path, path)) {
24 imported_path = &parsed_path;
31 parsed_paths_.emplace_back(std::move(path));
32 imported_path = &parsed_paths_.back();
35 bool seen_entry =
false;
36 for (
const auto& entry : entries_) {
37 if (entry.sym == sym && entry.tag == tag && fs::equivalent(entry.path, *imported_path)) {
43 if (!seen_entry) entries_.emplace_back(
Entry{*imported_path, sym, tag});
44 return {imported_path, fresh};
50 , world_(this, sym(name))
53 search_paths_.emplace_front(fs::path{});
56 if (
auto env_path = std::getenv(
"MIM_PLUGIN_PATH")) {
57 std::stringstream env_path_stream{env_path};
59 while (std::getline(env_path_stream, sub_path,
':'))
73 insert_ = ++search_paths_.begin();
77 ILOG(
"💾 loading plugin: '{}'", name);
80 WLOG(
"mim/plugin '{}' already loaded", name);
85 if (
auto path = fs::path{name.view()}; path.is_absolute() && fs::is_regular_file(path))
86 handle.reset(
dl::open(name.c_str()));
89 auto full_path = path / std::format(
"libmim_{}.{}", name,
dl::extension);
90 std::error_code ignore;
91 if (
bool reg_file = fs::is_regular_file(full_path, ignore); reg_file && !ignore) {
92 auto path_str = full_path.string();
93 if (handle.reset(
dl::open(path_str.c_str())); handle)
break;
99 if (!handle)
error(
"cannot open plugin '{}'", name);
101 if (
auto get_info =
reinterpret_cast<decltype(&
mim_get_plugin)
>(
dl::get(handle.get(),
"mim_get_plugin"))) {
102 auto plugin = get_info();
103 if (
version() != plugin.version) {
104 std::ostringstream oss;
105 std::print(oss,
"plugin {} has version {} while MimIR has version {}", plugin.name, plugin.version,
107 if (
flags().force_load)
108 std::cerr <<
"warning: " << oss.str() <<
'\n';
110 throw std::logic_error(oss.str());
114 if (
auto reg = plugin.register_normalizers) reg(normalizers_);
115 if (
auto reg = plugin.register_stages) reg(stages_);
118 error(
"mim/plugin has no 'mim_get_plugin()'");
123 if (
auto handle =
lookup(plugins_, plugin))
return dl::get(handle->get(), name);
std::pair< const fs::path *, bool > add(fs::path, Sym, ast::Tok::Tag)
Remembers an import or plugin directive and reports whether the resolved file is new.
void add_search_path(fs::path path)
const Version & version() const
MimIR Version.
bool is_loaded(Sym sym) const
void * get_fun_ptr(Sym plugin, const char *name)
const auto & search_paths() const
#define MIM_INSTALL_PREFIX
void * get(void *handle, const char *symbol_name)
void * open(const char *filename)
static constexpr auto extension
std::optional< fs::path > path_to_libmim()
Yields std::nullopt if an error occurred.
auto assert_emplace(C &container, Args &&... args)
Invokes emplace on container, asserts that insertion actually happened, and returns the iterator.
auto lookup(const C &container, const K &key)
Yields pointer to element (or the element itself if it is already a pointer), if found and nullptr ot...
mim::Plugin mim_get_plugin()
void error(std::format_string< Args... > fmt, Args &&... args)
Wraps std::format to throw T with a formatted message.
std::unique_ptr< void, void(*)(void *)> Handle