brewery
notashelf /
eb84d4617bc5fbc7e072d5d031248a021b618af3

nixir

public

Import-resolving Nix IR plugin

Star0tarball
clone
ssh://git@git.notashelf.dev:33/notashelf/nixir.git
src/irc/resolver.cppCpp111 lines3.2 KB
1
#include "resolver.h"
2
#include "parser.h"
3
#include <iostream>
4
#include <fstream>
5
#include <sstream>
6
#include <filesystem>
7
#include <regex>
8
9
namespace nix_irc {
10
11
namespace fs = std::filesystem;
12
13
struct Resolver::Impl {
14
    ResolverConfig config;
15
    std::vector<std::pair<std::string, std::string>> resolved_imports;
16
    std::unordered_set<std::string> visited;
17
    Parser parser;
18
    
19
    Impl(const ResolverConfig& cfg) : config(cfg) {}
20
    
21
    std::string resolve_path(const std::string& path, const std::string& from_file) {
22
        fs::path p(path);
23
        
24
        if (p.is_absolute()) {
25
            if (fs::exists(p)) return path;
26
            return "";
27
        }
28
        
29
        fs::path from_dir = fs::path(from_file).parent_path();
30
        fs::path candidate = from_dir / p;
31
        if (fs::exists(candidate)) return candidate.string();
32
        
33
        for (const auto& search : config.search_paths) {
34
            candidate = fs::path(search) / p;
35
            if (fs::exists(candidate)) return candidate.string();
36
        }
37
        
38
        return "";
39
    }
40
    
41
    ImportResult do_resolve(const std::string& path, const std::string& from_file) {
42
        std::string resolved = resolve_path(path, from_file);
43
        
44
        if (resolved.empty()) {
45
            return {false, "", "Cannot find file: " + path, nullptr};
46
        }
47
        
48
        if (visited.count(resolved)) {
49
            return {true, resolved, "", nullptr};
50
        }
51
        visited.insert(resolved);
52
        
53
        try {
54
            auto ast = parser.parse_file(resolved);
55
            return {true, resolved, "", ast};
56
        } catch (const std::exception& e) {
57
            return {false, "", e.what(), nullptr};
58
        }
59
    }
60
};
61
62
Resolver::Resolver(const ResolverConfig& config) : pImpl(std::make_unique<Impl>(config)) {}
63
Resolver::~Resolver() = default;
64
65
void Resolver::add_search_path(const std::string& path) {
66
    pImpl->config.search_paths.push_back(path);
67
}
68
69
void Resolver::set_search_paths(const std::vector<std::string>& paths) {
70
    pImpl->config.search_paths = paths;
71
}
72
73
ImportResult Resolver::resolve_import(const std::string& path, const std::string& from_file) {
74
    auto result = pImpl->do_resolve(path, from_file);
75
    if (result.success && result.ast) {
76
        pImpl->resolved_imports.push_back({path, result.path});
77
    }
78
    return result;
79
}
80
81
ImportResult Resolver::resolve_import(const Node& import_node, const std::string& from_file) {
82
    const ConstPathNode* path_node = import_node.get_if<ConstPathNode>();
83
    if (!path_node) {
84
        return {false, "", "Dynamic import not supported", nullptr};
85
    }
86
    return resolve_import(path_node->value, from_file);
87
}
88
89
std::vector<std::string> Resolver::get_resolved_files() const {
90
    std::vector<std::string> files;
91
    for (const auto& [orig, resolved] : pImpl->resolved_imports) {
92
        (void)orig;
93
        files.push_back(resolved);
94
    }
95
    return files;
96
}
97
98
std::vector<std::pair<std::string, std::string>> Resolver::get_imports() const {
99
    return pImpl->resolved_imports;
100
}
101
102
bool is_static_import(const Node& node) {
103
    return node.holds<ConstPathNode>();
104
}
105
106
std::string normalize_path(const std::string& path) {
107
    fs::path p(path);
108
    return fs::absolute(p).string();
109
}
110
111
}