14 Pass(
"ImportSolver", debug), m_debug_level(debug), m_libenv(libenv), m_ast()
19 m_root = root.parent_path();
21 for (
const auto& origin_import : std::ranges::reverse_view(origin_imports))
40 const auto package = source.import.toPackageString();
42 if (m_packages.contains(package))
45 m_packages[package].import.with_prefix |= source.import.with_prefix;
46 m_packages[package].import.is_glob |= source.import.is_glob;
47 for (auto&& symbol : source.import.symbols)
48 m_packages[package].import.symbols.push_back(symbol);
53 std::vector<ImportWithSource> temp = parseImport(source.file, source.import);
54 for (auto& additional_import : std::ranges::reverse_view(temp))
55 m_imports.push(additional_import);
75 const auto import_node = x.
constList()[1].constList();
76 const std::string
package = std::accumulate(
77 std::next(import_node.begin()),
79 import_node[0].string(),
80 [](const std::string& acc, const Node& elem) -> std::string {
81 return acc + "." + elem.string();
92 const auto import = m_packages[package].import;
96 std::string prefix =
import.prefix;
97 std::ranges::transform(
98 prefix, prefix.begin(),
100 return std::tolower(c);
105 .is_glob =
import.is_glob,
106 .with_prefix =
import.with_prefix,
107 .symbols =
import.symbols,
113 return std::make_pair(x,
true);
122 for (std::size_t i = 0; i < x.
constList().size(); ++i)
130 return std::make_pair(x,
false);
142 const auto path =
findFile(source,
import);
143 if (path.extension() ==
".arkm")
151 std::ranges::transform(
153 std::back_inserter(package_node.list()), [](
const std::string& stem) {
154 return Node(NodeType::String, stem);
156 module_node.push_back(package_node);
171 parser.
process(path.string(), code);
180 auto imports = parser.
imports();
181 std::vector<ImportWithSource> output;
182 std::ranges::transform(
184 std::back_inserter(output), [&path](
const Import& i) {
190 std::optional<std::filesystem::path>
testExtensions(
const std::filesystem::path& folder,
const std::string& package_path)
192 if (
auto code_path = folder / (package_path +
".ark"); std::filesystem::exists(code_path))
194 if (
auto module_path = folder / (package_path +
".arkm"); std::filesystem::exists(module_path))
201 const std::string package_path =
import.packageToPath();
203 return maybe_path.value();
208 if (
auto maybe_path =
testExtensions(path, package_path); maybe_path.has_value())
209 return maybe_path.value();
214 fmt::format(
"While processing file {}, couldn't import {}: file not found",
215 file.filename().string(),
import.toPackageString()),
217 file.generic_string(),
220 fmt::format(
"(import {})",
import.toPackageString())));
ArkScript homemade exceptions.
Lots of utilities about the filesystem.
Handle imports, resolve them with modules and everything.
Parse ArkScript code, but do not handle any import declarations.
std::stack< ImportWithSource > m_imports
std::filesystem::path m_root
Folder were the entry file is.
std::unordered_map< std::string, Package > m_packages
Package name to package AST & data mapping.
void process(const Node &origin_ast) override
Start processing the given AST.
std::filesystem::path findFile(const std::filesystem::path &file, const Import &import) const
Search for an import file, using the root file path.
std::vector< std::filesystem::path > m_libenv
std::pair< Node, bool > findAndReplaceImports(const Node &ast)
Visits the AST, looking for import nodes to replace with their parsed module version.
ImportSolver & setup(const std::filesystem::path &root, const std::vector< Import > &origin_imports)
Configure the ImportSolver.
ImportSolver(unsigned debug, const std::vector< std::filesystem::path > &libenv)
Create a new ImportSolver.
std::vector< ImportWithSource > parseImport(const std::filesystem::path &source, const Import &import)
Parse a given file and returns a list of its imports. The AST is parsed and stored in m_modules[impor...
std::vector< std::string > m_imported
List of imports, in the order they were found and parsed.
const Node & ast() const noexcept override
Output of the compiler pass.
void debug(const char *fmt, Args &&... args)
Write a debug level log using fmtlib.
void traceStart(std::string &&trace_name)
A node of an Abstract Syntax Tree for ArkScript.
NodeType nodeType() const noexcept
Return the node type.
const std::string & filename() const noexcept
Return the filename in which this node was created.
const std::vector< Node > & constList() const noexcept
Return the list of sub-nodes held by the node.
Namespace & arkNamespace() noexcept
Return the namespace held by the value (if the node type allows it)
std::size_t col() const noexcept
Get the column at which this node was created.
void push_back(const Node &node) noexcept
Every node has a list as well as a value so we can push_back on all node no matter their type.
std::size_t line() const noexcept
Get the line at which this node was created.
std::vector< Node > & list() noexcept
Return the list of sub-nodes held by the node.
void process(const std::string &filename, const std::string &code)
Parse the given code.
const Node & ast() const noexcept
const std::vector< Import > & imports() const
An interface to describe compiler passes.
std::string readFile(const std::string &name)
Helper to read a file.
std::optional< std::filesystem::path > testExtensions(const std::filesystem::path &folder, const std::string &package_path)
CodeError thrown by the compiler (parser, macro processor, optimizer, and compiler itself)
std::string toPackageString() const
std::shared_ptr< Node > ast