♻️ now use a value object to represente snakefile values.

main
bog 2023-10-15 22:50:43 +02:00
parent 21cb7db86f
commit c6a00a7c7b
8 changed files with 148 additions and 71 deletions

View File

@ -26,6 +26,7 @@ snake_lib = static_library('snake',
'src/Loader.cpp',
'src/Executor.cpp',
'src/Finder.cpp',
'src/Value.cpp',
],
dependencies: [
dependency('sqlite3')

View File

@ -42,7 +42,8 @@ namespace sn
entry.first);
itr == std::end(files))
{
auto path = format_path(entry.first);
auto path = format_path
(std::make_shared<Value>(entry.first))->path().string();
files.push_back(path);
}
@ -57,19 +58,19 @@ namespace sn
}
}
// Get modified files
// ------------------
m_state->init(files);
auto modified_files = m_state->get_modified_files(files);
// Build DAG
// ---------
auto dag = std::make_shared<DAG>();
std::function<void(std::filesystem::path const&)>
add = [&](std::filesystem::path file) {
file = format_path(file);
file = format_path(std::make_shared<Value>(file))->path().string();
if (!dag->exists(file))
{
@ -132,7 +133,6 @@ namespace sn
else
{
// TODO TRY GENERICS
std::cout << "-> " << file << std::endl;
}
m_state->update(file);
@ -144,18 +144,19 @@ namespace sn
}
}
std::vector<std::string>
std::vector<std::shared_ptr<Value>>
Interpreter::get_value(std::shared_ptr<Node> node) const
{
if (node->type() == NODE_IDENT)
{
return { node->repr() };
return { std::make_shared<Value>(node->repr()) };
}
else if (node->type() == NODE_VAR)
{
if (auto var = m_sym.get(node->repr());
var)
{
return var->values;
}
else
@ -165,32 +166,52 @@ namespace sn
}
else if (node->type() == NODE_ARRAY)
{
std::vector<std::string> values;
std::vector<std::shared_ptr<Value>> values;
for (size_t i=0; i<node->size(); i++)
{
std::string text = (*node->get(i))->repr();
std::vector<std::string> vals;
std::vector<std::shared_ptr<Value>> vals;
if (text.find('*') != std::string::npos)
// wildcard array constructor
{
auto candidate =
auto candidate_pathes =
m_finder->get_paths(m_loader->find_snakefile().parent_path());
std::vector<std::shared_ptr<Value>> candidate;
std::transform(std::begin(candidate_pathes),
std::end(candidate_pathes),
std::back_inserter(candidate),
[](auto const& element){
return std::make_shared<Value>(element);
});
std::copy(std::begin(m_files), std::end(m_files),
std::back_inserter(candidate));
std::sort(std::begin(candidate), std::end(candidate));
std::sort(std::begin(candidate), std::end(candidate),
[](auto const& lhs,
auto const& rhs){
return lhs->path() < rhs->path();
});
auto pred = [](std::shared_ptr<Value> const& lhs,
std::shared_ptr<Value> const& rhs){
return *lhs == *rhs;
};
candidate.erase(std::unique(std::begin(candidate),
std::end(candidate)),
std::end(candidate),
pred),
std::end(candidate));
std::copy_if(std::begin(candidate),
std::end(candidate),
std::back_inserter(vals),
[&](auto f){
return m_finder->match(text, f);
return m_finder->match(text, f->path().string());
});
}
else
@ -215,7 +236,7 @@ namespace sn
// Extension replacement
{
auto old_values = get_value(var);
std::vector<std::string> values;
std::vector<std::shared_ptr<Value>> values;
std::string src_extension = val->repr();
std::string dest_extension = (*node->get(2))->repr();
@ -223,16 +244,18 @@ namespace sn
std::back_inserter(values),
[src_extension, dest_extension]
(auto const& val){
auto val_p = std::filesystem::path(val);
auto val_p = std::filesystem::path(val->path());
if (val_p.has_extension()
&& val_p.extension() == src_extension)
{
return val_p.replace_extension(dest_extension);
return
std::make_shared<Value>
(val_p.replace_extension(dest_extension));
}
else
{
return val_p;
return std::make_shared<Value>(val_p);
}
});
@ -242,14 +265,15 @@ namespace sn
// Extension modifier
{
auto old_values = get_value(var);
std::vector<std::string> values;
std::vector<std::shared_ptr<Value>> values;
std::string extension = val->repr();
std::transform(std::begin(old_values), std::end(old_values),
std::back_inserter(values),
[extension](auto const& val){
auto val_p = std::filesystem::path(val);
return val_p.replace_extension(extension);
auto val_p = std::filesystem::path(val->path());
return std::make_shared<Value>
(val_p.replace_extension(extension));
});
return values;
@ -291,17 +315,19 @@ namespace sn
path);
itr != std::end(entry.second))
{
result.push_back(format_path(entry.first));
result.push_back
(format_path
(std::make_shared<Value>(entry.first))->path());
}
}
return result;
}
std::vector<std::filesystem::path>
std::vector<std::shared_ptr<Value>>
Interpreter::collect(std::shared_ptr<Node> node) const
{
std::vector<std::filesystem::path> results;
std::vector<std::shared_ptr<Value>> results;
switch (node->type())
{
@ -310,8 +336,8 @@ namespace sn
auto deps = *node->get(1);
auto block = *node->get(2);
std::vector<std::string> target_values;
std::vector<std::string> target_values_verbatim;
std::vector<std::shared_ptr<Value>> target_values;
std::vector<std::shared_ptr<Value>> target_values_verbatim;
for (size_t i=0; i<target_node->size(); i++)
{
@ -335,8 +361,8 @@ namespace sn
}
}
std::vector<std::string> dep_values;
std::vector<std::string> dep_values_verbatim;
std::vector<std::shared_ptr<Value>> dep_values;
std::vector<std::shared_ptr<Value>> dep_values_verbatim;
for (size_t i=0; i<deps->size(); i++)
{
@ -381,8 +407,14 @@ namespace sn
std::sort(std::begin(results), std::end(results));
auto pred = [](std::shared_ptr<Value> const& lhs,
std::shared_ptr<Value> const& rhs){
return *lhs == *rhs;
};
results.erase(std::unique(std::begin(results),
std::end(results)),
std::end(results),
pred),
std::end(results));
return results;
@ -419,8 +451,8 @@ namespace sn
break;
}
std::vector<std::string> target_values;
std::vector<std::string> target_values_verbatim;
std::vector<std::shared_ptr<Value>> target_values;
std::vector<std::shared_ptr<Value>> target_values_verbatim;
for (size_t i=0; i<target_node->size(); i++)
{
@ -438,8 +470,8 @@ namespace sn
std::placeholders::_1));
}
std::vector<std::string> dep_values;
std::vector<std::string> dep_values_verbatim;
std::vector<std::shared_ptr<Value>> dep_values;
std::vector<std::shared_ptr<Value>> dep_values_verbatim;
for (size_t i=0; i<deps->size(); i++)
{
@ -459,12 +491,14 @@ namespace sn
{
for (auto dep: dep_values)
{
m_dependencies[target].push_back(dep);
m_dependencies[target->path().string()]
.push_back(dep->path().string());
}
m_sym.declare("IN", dep_values_verbatim);
m_sym.declare("OUT", target_values_verbatim);
m_scripts[target] = scripts(block);
m_scripts[target->path().string()] = scripts(block);
}
} break;
@ -497,12 +531,15 @@ namespace sn
for (auto val: values)
{
if (std::filesystem::is_regular_file(val))
if (std::filesystem::is_regular_file(val->path()))
{
val = std::filesystem::relative(val, m_loader->find_snakefile().parent_path()).string();
val->set_path(std::filesystem::relative
(val->path(),
m_loader->find_snakefile().parent_path()).string());
}
script += vsep + val;
script += vsep + val->path().string();
vsep = " ";
}
}
@ -518,15 +555,16 @@ namespace sn
return m_executor->execute(script);
}
std::filesystem::path
Interpreter::format_path(std::filesystem::path path) const
std::shared_ptr<Value>
Interpreter::format_path(std::shared_ptr<Value> path) const
{
if (std::filesystem::exists(path))
if (std::filesystem::exists(path->path()))
{
return std::filesystem::canonical(path);
return std::make_shared<Value>
(std::filesystem::canonical(path->path()));
}
return std::filesystem::absolute(path);
return std::make_shared<Value>
(std::filesystem::absolute(path->path()));
}
}

View File

@ -14,25 +14,6 @@ namespace sn
{
SN_ERROR(run_error);
/**
* Represents a snakefile value.
* (e.g a file, an array of files ...)
**/
struct Value {
Value(std::filesystem::path p_file)
: file { p_file }
{
}
Value(std::vector<std::filesystem::path> p_array)
: array { p_array }
{
}
std::optional<std::filesystem::path> file;
std::optional<std::vector<std::filesystem::path>> array;
};
/**
* Process a snakefile AST and run build commands.
* @see Node
@ -56,7 +37,7 @@ namespace sn
std::shared_ptr<Executor> m_executor;
std::shared_ptr<Finder> m_finder;
std::ostream& m_ostream;
std::vector<std::filesystem::path> m_files;
std::vector<std::shared_ptr<Value>> m_files;
std::unordered_map<std::filesystem::path,
std::vector<std::filesystem::path>> m_dependencies;
@ -65,12 +46,13 @@ namespace sn
std::vector<std::string>> m_scripts;
SymTable m_sym;
std::vector<std::string> get_value(std::shared_ptr<Node> node) const;
std::vector<std::shared_ptr<Value>>
get_value(std::shared_ptr<Node> node) const;
std::vector<std::filesystem::path>
targets(std::filesystem::path path) const;
std::vector<std::filesystem::path>
std::vector<std::shared_ptr<Value>>
collect(std::shared_ptr<Node> node) const;
void process(std::shared_ptr<Node> node);
@ -79,8 +61,8 @@ namespace sn
std::string execute(std::string const& script) const;
std::filesystem::path
format_path(std::filesystem::path path) const;
std::shared_ptr<Value>
format_path(std::shared_ptr<Value> path) const;
};
}

View File

@ -11,7 +11,7 @@ namespace sn
}
void SymTable::declare(std::string const& name,
std::vector<std::string> const& values)
std::vector<std::shared_ptr<Value>> const& values)
{
m_vars[name] = Var { values };
}

View File

@ -3,6 +3,7 @@
#include "commons.hpp"
#include "Node.hpp"
#include "Value.hpp"
namespace sn
{
@ -10,7 +11,7 @@ namespace sn
* A variable of the snakefile.
**/
struct Var {
std::vector<std::string> values;
std::vector<std::shared_ptr<Value>> values;
};
/**
@ -24,7 +25,7 @@ namespace sn
virtual ~SymTable();
void declare(std::string const& name,
std::vector<std::string> const& values);
std::vector<std::shared_ptr<Value>> const& values);
std::optional<Var> get(std::string const& name) const;

23
src/Value.cpp Normal file
View File

@ -0,0 +1,23 @@
#include "Value.hpp"
namespace sn
{
/*explicit*/ Value::Value(std::filesystem::path path)
: m_path { path }
{
}
/*virtual*/ Value::~Value()
{
}
void Value::set_path(std::filesystem::path path)
{
m_path = path;
}
bool Value::operator==(Value const& rhs) const
{
return m_path == rhs.m_path;
}
}

28
src/Value.hpp Normal file
View File

@ -0,0 +1,28 @@
#ifndef sn_VALUE_HPP
#define sn_VALUE_HPP
#include "commons.hpp"
namespace sn
{
/**
* Represents a snakefile value.
* (e.g a file, an array of files ...)
**/
class Value
{
public:
explicit Value(std::filesystem::path path);
virtual ~Value();
std::filesystem::path path() const { return m_path; }
void set_path(std::filesystem::path path);
bool operator==(Value const& rhs) const;
private:
std::filesystem::path m_path;
};
}
#endif

View File

@ -137,7 +137,8 @@ public:
return;
}
INFO(str << "not found");
INFO("'" << str << "' not found");
REQUIRE(std::any_of(std::begin(vec), std::end(vec), [&](auto const& line){
return sort_line(line) == sort_line(str);
}));
@ -375,6 +376,7 @@ TEST_CASE_METHOD(InterpreterTest, "Interpreter_replace_ext")
ss << "}" << std::endl;
auto res = TEST_RUN(ss.str(), std::filesystem::path("a"));
test_contains("x.h y.h z.d w t.h", res);
}
}
@ -434,10 +436,11 @@ TEST_CASE_METHOD(InterpreterTest, "Interpreter_array_constructor")
result = "src/second.py src/fourth.hpp";
auto res = TEST_RUN(ss.str(), std::filesystem::path("src/second.py"));
test_contains(result, res);
}
SECTION("all in sub directories")
SECTION("all in sub directories")
{
std::stringstream ss;
ss << "x y z -> (src/build/target/*) {" << std::endl;
@ -449,6 +452,7 @@ TEST_CASE_METHOD(InterpreterTest, "Interpreter_array_constructor")
auto res = TEST_RUN(ss.str(),
std::filesystem::path("src/build/target/sixth"));
test_contains(result, res);
}
}