♻️ now use a value object to represente snakefile values.
parent
21cb7db86f
commit
c6a00a7c7b
|
@ -26,6 +26,7 @@ snake_lib = static_library('snake',
|
|||
'src/Loader.cpp',
|
||||
'src/Executor.cpp',
|
||||
'src/Finder.cpp',
|
||||
'src/Value.cpp',
|
||||
],
|
||||
dependencies: [
|
||||
dependency('sqlite3')
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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 };
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue