Skip to content

Commit

Permalink
resolver: rework resolvers & parser manager
Browse files Browse the repository at this point in the history
  • Loading branch information
jumanji144 committed Nov 19, 2023
1 parent e341c26 commit c13ada4
Show file tree
Hide file tree
Showing 13 changed files with 131 additions and 122 deletions.
3 changes: 2 additions & 1 deletion lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ add_library(libpl ${LIBRARY_TYPE}
source/pl/core/preprocessor.cpp
source/pl/core/validator.cpp

source/pl/core/resolvers.cpp
source/pl/core/resolver.cpp
source/pl/core/error.cpp

source/pl/lib/std/pragmas.cpp
Expand All @@ -70,6 +70,7 @@ add_library(libpl ${LIBRARY_TYPE}
source/pl/lib/std/core.cpp
source/pl/lib/std/hash.cpp
source/pl/lib/std/random.cpp
source/pl/core/resolvers.cpp
)

if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
Expand Down
2 changes: 0 additions & 2 deletions lib/include/pl/api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ namespace pl::api {

static constexpr Source EmptySource = { "", "" };

using IncludeResolver = std::function<hlp::Result<Source*, std::string>(const std::string&)>;

/**
* @brief A type representing a custom section
*/
Expand Down
7 changes: 5 additions & 2 deletions lib/include/pl/core/parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,9 @@ namespace pl::core {
using TokenIter = std::vector<Token>::const_iterator;

explicit Parser() = default;
explicit Parser(ParserManager* parserManager) : m_parserManager(parserManager) {}
~Parser() = default;

CompileResult<AST> parse(const std::string &sourceCode, const std::vector<Token> &tokens);
CompileResult<std::vector<std::shared_ptr<ast::ASTNode>>> parse(const std::string &sourceCode, const std::vector<Token> &tokens);

const auto &getTypes() { return this->m_types; }

Expand All @@ -45,6 +44,10 @@ namespace pl::core {
this->m_currNamespace.push_back(path);
}

void setParserManager(ParserManager* parserManager) {
this->m_parserManager = parserManager;
}

private:
std::optional<err::PatternLanguageError> m_error;
TokenIter m_curr;
Expand Down
17 changes: 11 additions & 6 deletions lib/include/pl/core/parser_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@
#include <pl/api.hpp>
#include <pl/core/ast/ast_node.hpp>
#include <pl/core/errors/error.hpp>
#include <pl/core/resolver.hpp>

namespace pl::core {
#include <utility>

using AST = std::vector<std::shared_ptr<ast::ASTNode>>;
namespace pl::core {

class ParserManager {
public:
explicit ParserManager() = default;

explicit ParserManager(const api::IncludeResolver& resolver) : m_includeResolver(resolver) {}
CompileResult<std::vector<std::shared_ptr<ast::ASTNode>>> parse(const api::Source* source, const std::string &namespacePrefix = "");

CompileResult<AST> parse(const std::string &code);
void setResolvers(Resolver* resolvers) {
m_resolvers = resolvers;
}

private:
std::map<std::string, AST> m_astCache;
api::IncludeResolver m_includeResolver;
std::map<std::string, std::vector<std::shared_ptr<ast::ASTNode>>> m_astCache;
Resolver* m_resolvers = nullptr;
};

}
11 changes: 5 additions & 6 deletions lib/include/pl/core/preprocessor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
#include <pl/api.hpp>
#include <pl/helpers/types.hpp>
#include <pl/core/errors/error.hpp>
#include <pl/core/resolver.hpp>

#include <utility>
#include <wolv/io/fs.hpp>

namespace pl::core {

Expand All @@ -36,8 +36,8 @@ namespace pl::core {
return this->m_onlyIncludeOnce;
}

void setIncludeResolver(const api::IncludeResolver &resolver) {
this->m_includeResolver = resolver;
void setResolver(Resolver* resolvers) {
m_resolver = resolvers;
}

private:
Expand Down Expand Up @@ -73,10 +73,9 @@ namespace pl::core {
std::unordered_map<std::string, std::pair<std::string, u32>> m_defines;
std::unordered_map<std::string, std::vector<std::pair<std::string, u32>>> m_pragmas;

std::set<std::fs::path> m_onceIncludedFiles;

api::IncludeResolver m_includeResolver;
std::set<std::string> m_onceIncludedFiles;

Resolver *m_resolver = nullptr;
PatternLanguage *m_runtime = nullptr;

size_t m_offset = 0;
Expand Down
36 changes: 7 additions & 29 deletions lib/include/pl/core/resolver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,16 @@

namespace pl::core {

using Resolver = std::function<hlp::Result<api::Source, std::string>(const std::string&)>;
using SourceResolver = std::function<hlp::Result<api::Source, std::string>(const std::string&)>;

class Resolvers {
class Resolver {

public:
Resolvers() = default;
Resolver() = default;

hlp::Result<api::Source*, std::string> resolve(const std::string& path);
inline hlp::Result<api::Source*, std::string> operator()(const std::string& path) { // forward for include resolver functional interface
return resolve(path);
}

inline void registerProtocol(const std::string& protocol, const Resolver& resolver) {
inline void registerProtocol(const std::string& protocol, const SourceResolver& resolver) {
m_protocolResolvers[protocol] = resolver;
}

Expand All @@ -39,33 +36,14 @@ namespace pl::core {
return setSource(source, api::Source(code, source));
}

inline void setDefaultResolver(const Resolver& resolver) const {
inline void setDefaultResolver(const SourceResolver& resolver) const {
m_defaultResolver = resolver;
}

private:
mutable std::map<std::string, Resolver> m_protocolResolvers; // for git://, http(s)://
mutable Resolver m_defaultResolver;
mutable std::map<std::string, SourceResolver> m_protocolResolvers; // for git://, http(s)://
mutable SourceResolver m_defaultResolver;
mutable std::map<std::string, api::Source> m_cachedSources;
};

class FileResolver {
public:

FileResolver() = default;
explicit FileResolver(const std::vector<std::fs::path>& includePaths) : m_includePaths(includePaths) { }

hlp::Result<api::Source, std::string> resolve(const std::string& path);
inline hlp::Result<api::Source, std::string> operator()(const std::string& path) {
return resolve(path);
}

void setIncludePaths(const std::vector<std::fs::path>& includePaths) const {
this->m_includePaths = includePaths;
}

private:
mutable std::vector<std::fs::path> m_includePaths;
};

}
28 changes: 28 additions & 0 deletions lib/include/pl/core/resolvers.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// Created by justus on 19.11.23.
//

#pragma once

#include <pl/core/resolver.hpp>

namespace pl::core {
class FileResolver {
public:

FileResolver() = default;
explicit FileResolver(const std::vector<std::fs::path>& includePaths) : m_includePaths(includePaths) { }

hlp::Result<api::Source, std::string> resolve(const std::string& path);
inline hlp::Result<api::Source, std::string> operator()(const std::string& path) {
return resolve(path);
}

void setIncludePaths(const std::vector<std::fs::path>& includePaths) const {
this->m_includePaths = includePaths;
}

private:
mutable std::vector<std::fs::path> m_includePaths;
};
}
14 changes: 12 additions & 2 deletions lib/include/pl/pattern_language.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <pl/core/token.hpp>
#include <pl/core/errors/error.hpp>
#include <pl/core/resolver.hpp>
#include <pl/core/parser_manager.hpp>

#include <pl/helpers/types.hpp>

Expand Down Expand Up @@ -185,7 +186,7 @@ namespace pl {
*/
void setIncludePaths(const std::vector<std::fs::path>& paths) const;

void setIncludeResolver(const api::IncludeResolver &resolver) const;
void setResolver(const core::Resolver& resolver);

/**
* @brief Registers a callback to be called when a dangerous function is being executed
Expand Down Expand Up @@ -311,6 +312,14 @@ namespace pl {
return this->m_internals;
}

[[nodiscard]] core::Resolver& getResolver() {
return this->m_resolvers;
}

[[nodiscard]] const core::Resolver& getResolver() const {
return this->m_resolvers;
}

/**
* Adds a new cleanup callback that is called when the runtime is reset
* @note This is useful for built-in functions that need to clean up their state
Expand Down Expand Up @@ -345,7 +354,8 @@ namespace pl {
std::vector<core::err::CompileError> m_compErrors;
std::optional<core::err::PatternLanguageError> m_currError;

core::Resolvers m_resolvers;
core::Resolver m_resolvers;
core::ParserManager m_parserManager;

std::map<u64, std::vector<std::shared_ptr<ptrn::Pattern>>> m_patterns;
std::map<u64, wolv::container::IntervalTree<ptrn::Pattern*, u64, 5>> m_flattenedPatterns;
Expand Down
10 changes: 4 additions & 6 deletions lib/source/pl/core/preprocessor.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#include <pl/core/preprocessor.hpp>
#include <pl/core/errors/preprocessor_errors.hpp>

#include <fmt/format.h>

#include <wolv/utils/string.hpp>

namespace pl::core {
Expand All @@ -27,7 +25,7 @@ namespace pl::core {
this->m_defines = other.m_defines;
this->m_pragmas = other.m_pragmas;
this->m_onceIncludedFiles = other.m_onceIncludedFiles;
this->m_includeResolver = other.m_includeResolver;
this->m_resolver = other.m_resolver;
this->m_onlyIncludeOnce = false;
this->m_pragmaHandlers = other.m_pragmaHandlers;
this->m_directiveHandlers = other.m_directiveHandlers;
Expand Down Expand Up @@ -204,18 +202,18 @@ namespace pl::core {
return;
}

const std::fs::path includePath = includeFile->substr(1, includeFile->length() - 2);
const std::string includePath = includeFile->substr(1, includeFile->length() - 2);

// determine if we should include this file
if (this->m_onceIncludedFiles.contains(includePath))
return;

if(!m_includeResolver) {
if(m_resolver == nullptr) {
error_desc("Unable to lookup results", "No include resolver was set.");
return;
}

auto [resolved, error] = this->m_includeResolver(includePath);
auto [resolved, error] = this->m_resolver->resolve(includePath);

if(!resolved.has_value()) {
for (const auto &item: error) {
Expand Down
41 changes: 41 additions & 0 deletions lib/source/pl/core/resolver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <pl/core/resolver.hpp>

using namespace pl::core;
using namespace pl::api;
using namespace pl::hlp;

Result<Source *, std::string> Resolver::resolve(const std::string &path) {
using result_t = Result<Source *, std::string>;
// look in cache
auto it = m_cachedSources.find(path);
if (it != m_cachedSources.end())
return result_t::good(&it->second);

Result<Source, std::string> result;

// look for protocol
if(!m_protocolResolvers.empty()){
auto protocolEnd = path.find("://");
if (protocolEnd != std::string::npos) {
auto protocol = path.substr(0, protocolEnd);
auto protocolIt = m_protocolResolvers.find(protocol);
if (protocolIt != m_protocolResolvers.end()) {
result = protocolIt->second(path);
}
}
}

if(!result.is_ok()) {
if (!m_defaultResolver)
return result_t::err("No possible way to resolve path " + path + " and no default resolver set");

result = m_defaultResolver(path);
}

if (result.is_ok()) {
m_cachedSources[path] = result.unwrap();
return result_t::good(&m_cachedSources[path]);
}

return result_t::err(result.unwrap_errs());
}
41 changes: 2 additions & 39 deletions lib/source/pl/core/resolvers.cpp
Original file line number Diff line number Diff line change
@@ -1,48 +1,11 @@
#include <pl/core/resolver.hpp>
#include <wolv/io/file.hpp>
#include <pl/core/resolvers.hpp>

#include <iostream>
#include <wolv/io/file.hpp>

using namespace pl::core;
using namespace pl::api;
using namespace pl::hlp;

Result<Source *, std::string> Resolvers::resolve(const std::string &path) {
using result_t = Result<Source *, std::string>;
// look in cache
auto it = m_cachedSources.find(path);
if (it != m_cachedSources.end())
return result_t::good(&it->second);

Result<Source, std::string> result;

// look for protocol
if(!m_protocolResolvers.empty()){
auto protocolEnd = path.find("://");
if (protocolEnd != std::string::npos) {
auto protocol = path.substr(0, protocolEnd);
auto protocolIt = m_protocolResolvers.find(protocol);
if (protocolIt != m_protocolResolvers.end()) {
result = protocolIt->second(path);
}
}
}

if(!result.is_ok()) {
if (!m_defaultResolver)
return result_t::err("No possible way to resolve path " + path + " and no default resolver set");

result = m_defaultResolver(path);
}

if (result.is_ok()) {
m_cachedSources[path] = result.unwrap();
return result_t::good(&m_cachedSources[path]);
}

return result_t::err(result.unwrap_errs());
}

Result<Source, std::string> FileResolver::resolve(const std::string &path) {
using result_t = Result<Source, std::string>;

Expand Down
Loading

0 comments on commit c13ada4

Please sign in to comment.