Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 71 additions & 11 deletions ffs/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//
// SPDX-License-Identifier: BSD-2-Clause

#include "starlark/interpreter.h"
#include "starlark/parser.h"
#include "starlark/token.h"
#include "starlark/tokenizer.h"
Expand Down Expand Up @@ -54,22 +55,65 @@ build_files_from_pattern(std::filesystem::path const &from, std::string_view pat
return std::nullopt;
}

auto root_path = project_root(from);
if (!root_path) {
std::cerr << "Unable to find ffs project root for folder '" << from << "'.\n";
return std::nullopt;
}

std::vector<std::filesystem::path> found;
for (auto const &dir : std::filesystem::recursive_directory_iterator{from}) {
if (std::filesystem::exists(dir.path() / "BUILD.bazel")) {
found.push_back(dir.path() / "BUILD.bazel");
if (dir.path().filename() == "BUILD.bazel") {
found.push_back(dir);
}
}

return found;
}

struct Target {
std::string name;
};

// TODO(robinlinden): This should be less silly.
std::optional<std::vector<Target>> targets_from_build_file(std::filesystem::path bf) {
std::ifstream input{bf};
if (!input) {
return std::nullopt;
}

std::string content{std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>()};
auto program = starlark::parse(content);
if (!program) {
return std::nullopt;
}

std::vector<Target> targets;

starlark::Interpreter interpreter;

static constexpr auto kIgnore = [](auto const &) { return starlark::Value{}; };
auto store_target_name = [&](std::vector<starlark::NativeArgument> args) {
auto it = std::ranges::find_if(
args, [](auto &name) { return name == "name"; }, &starlark::NativeArgument::name);
if (it != std::ranges::end(args) && std::holds_alternative<std::string>(it->value.v)) {
targets.emplace_back(std::move(std::get<std::string>(it->value.v)));
}

return starlark::Value{0};
};

interpreter.variables["cc_binary"] =
starlark::Value{std::make_shared<starlark::NativeFn>(store_target_name)};
interpreter.variables["cc_library"] =
starlark::Value{std::make_shared<starlark::NativeFn>(store_target_name)};
interpreter.variables["cc_test"] =
starlark::Value{std::make_shared<starlark::NativeFn>(store_target_name)};
interpreter.variables["glob"] = starlark::Value{std::make_shared<starlark::NativeFn>(kIgnore)};

auto res = interpreter.run(*program);
if (!res) {
std::cerr << "Query failed. :(\n";
return std::nullopt;
}

return targets;
}

int run_debug(int argc, char **argv) {
assert(argc == 2);

Expand Down Expand Up @@ -104,18 +148,34 @@ int run_query(int argc, char **argv) {
assert(argc == 3);

auto cwd = std::filesystem::current_path();
auto root_path = project_root(cwd);
if (!root_path) {
std::cerr << "Unable to find ffs project root for folder '" << cwd << "'.\n";
return 1;
}

auto build_files = build_files_from_pattern(cwd, argv[2]);
if (!build_files) {
std::cerr << "Failed to find build files.\n";
return 1;
}

// TODO(robinlinden): Get targets from build files.
bool failure = false;
for (auto const &build_file : *build_files) {
std::cout << build_file << '\n';
auto targets = targets_from_build_file(build_file);
if (!targets) {
std::cerr << "Resolving targets for build file " << build_file << " failed.\n";
failure = true;
continue;
}

auto package = build_file.parent_path().lexically_relative(*root_path).string();
for (auto const &target : *targets) {
std::cout << "//" << package << ":" << target.name << '\n';
}
}

return 0;
return failure ? 1 : 0;
}

} // namespace
Expand Down
14 changes: 5 additions & 9 deletions starlark/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,6 @@ class Interpreter {
return result;
}

std::optional<Value> run(auto const &) {
// TODO(robinlinden): Delete this.
return std::nullopt;
}

std::optional<Value> run(Statement const &stmt) {
return std::visit([this](auto const &s) { return run(s); }, stmt);
}

std::optional<Value> run(AssignStmt const &stmt) {
auto value = run(stmt.value);
if (!value) {
Expand Down Expand Up @@ -180,6 +171,11 @@ class Interpreter {

return (**target)(std::move(native_args));
}

std::optional<Value> run(LoadStmt const &load) {
std::ignore = load; // TODO(robinlinden): Implement.
return Value{};
}
};

} // namespace starlark
Expand Down