AST reprogramming #5

Open
TopchetoEU wants to merge 15 commits from TopchetoEU/ast-reporgramming into master
9 changed files with 157 additions and 170 deletions
Showing only changes of commit d6175a696d - Show all commits

View File

@ -1,35 +1,19 @@
export lsproj = $(bin)/lsproj$(exe)
export lsdep = $(bin)/lsdep$(exe)
export lsinc = $(bin)/lsinc$(exe)
export flags += "-I$(inc)" -D$(OS) -DPPC_VERSION_MAJOR=$(version-major) -DPPC_VERSION_MINOR=$(version-minor) -DPPC_VERSION_BUILD=$(version-build)
$(shell make -f scripts/ls.mak lsinc=$(lsinc) lsproj=$(lsproj) src=$(src) "flags=$(flags)" all)
$(shell make -f scripts/ls.mak lsinc=$(lsinc) lsdep=$(lsdep) src=$(src) "flags=$(flags)" all)
rwildcard=$(foreach d, $(wildcard $(1:=/*)),\
$(call rwildcard,$d,$2)\
$(filter $(subst *,%,$2),$d)\
)
uniq=$(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
modoutput=$(shell ./$(lsproj) $(src) $1 output)
deps=$(strip \
$(foreach dep, $(shell ./$(lsproj) $(src) $1 deps),\
$(if $(wildcard src/$(dep)), $(dep),\
$(error The module '$(dep)' (dependency of '$1') doesn't exist)\
)\
)\
)
rdeps=$(call uniq,$(strip \
$(foreach dep, $(call deps,$1),\
$(call rdeps,$(dep))\
$(dep)\
)\
))
deps=$(shell $(lsdep) --dir=deps $1)
rdeps=$(shell $(lsdep) --dir=deps --rec $1)
fdeps=$(foreach dep,$(call deps,$1),$(bin)/lib$(lib)$(call modoutput,$(dep))$(so))
frdeps=$(foreach dep,$(call rdeps,$1),$(bin)/lib$(lib)$(call modoutput,$(dep))$(so))
ldeps=$(foreach dep,$(call deps,$1),-l$(lib)$(call modoutput,$(dep)))
lrdeps=$(foreach dep,$(call rdeps,$1),-l$(lib)$(call modoutput,$(dep)))
frdeps=$(shell $(lsdep) --dir=deps --rec --transform=$(bin)/lib$(lib)*$(so) $1)
ldeps=$(shell $(lsdep) --dir=deps --transform=-l$(lib) $1)
modules = $(patsubst $(src)/%/,$(bin)/lib$(lib)%$(so),$(filter-out $(src)/$(mainmodule)/,$(wildcard $(src)/*/)))
sources = $(call rwildcard,$(src)/$1,*.cc)

View File

@ -1,9 +1,11 @@
all: $(lsproj) $(lsinc)
all: $(lsdep) $(lsinc)
$(lsproj): $(src)/lsproj.cc
$(lsdep): $(src)/lsdep.cc
$(call mkdir,$(dir $@))
echo - Compiling lsdep.cc... >&2
$(CXX) $(flags) $^ -o $@
$(lsinc): $(src)/lsinc.cc
echo - Compiling lsinc.cc... >&2
$(call mkdir,$(dir $@))
$(CXX) $(flags) $^ -o $@

View File

@ -1,2 +0,0 @@
lang
utils

146
src/lsdep.cc Normal file
View File

@ -0,0 +1,146 @@
#include <fstream>
#include <iostream>
#include <vector>
#include <set>
#include <string>
#include <filesystem>
#include <algorithm>
using namespace std::string_literals;
using std::size_t;
namespace fs = std::filesystem;
fs::path proj_dir;
bool recursive = false;
std::string prefix = "", suffix = "";
static inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
}
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}
static inline void trim(std::string &s) {
rtrim(s);
ltrim(s);
}
static bool read_line(std::istream &str, std::string &res) {
if (str.eof()) return false;
std::getline(str, res);
trim(res);
return true;
}
void read_project_rec(const std::string &name, std::set<std::string> &res, bool rec = false) {
static std::set<std::string> prev;
if (!prev.emplace(name).second) throw name + ": Circular dependency detected.";
std::ifstream f(proj_dir / name);
std::string line;
while (read_line(f, line)) {
if (line.find('#') != std::string::npos) {
line = line.substr(0, line.find('#'));
}
trim(line);
if (line.size() == 0) continue;
if (line == name) throw name + ": Depends on itself.";
res.emplace(line);
if (rec) read_project_rec(line, res);
}
prev.erase(name);
}
void print_err(const std::string &error, const std::string &context) {
std::cerr << context << ": " << error;
}
void set_transform(const std::string &val) {
size_t i = 0;
bool last_percent = false;
bool is_prefix = true;
prefix = "", suffix = "";
for (; i < val.length(); i++) {
if (is_prefix) {
if (val[i] == '*') {
if (last_percent) {
last_percent = false;
}
else {
last_percent = true;
continue;
}
}
else if (last_percent) {
is_prefix = false;
last_percent = false;
}
}
if (is_prefix) prefix += val[i];
else suffix += val[i];
}
}
bool process_arg(std::string arg) {
if (arg.find("--") != 0) return false;
arg = arg.substr(2);
if (arg == "rec") {
recursive = true;
return true;
}
else if (arg.find("transform=") == 0) {
arg = arg.substr(10);
set_transform(arg);
}
else if (arg.find("dir=") == 0) {
arg = arg.substr(4);
proj_dir = arg;
}
else {
throw "Incorrect usage. Syntax: [--rec] [--transform=prefix%suffix] [--dir=dir] [projects...]"s;
}
return true;
}
int main(int argc, const char *argv[]) {
try {
argc--;
argv++;
std::set<std::string> deps;
while (argc > 0 && process_arg(argv[0])) {
argc--;
argv++;
}
while (argc > 0) {
// if (recursive) read_project_rec(argv[0], deps);
// else read_project(argv[0], deps);
read_project_rec(argv[0], deps, recursive);
argc--;
argv++;
}
for (auto &dep : deps) {
std::cout << prefix + dep + suffix << std::endl;
}
return 0;
}
catch (std::string err) {
std::cerr << "error: lsdep: " << err << std::endl;
}
return -1;
}

View File

@ -108,7 +108,7 @@ int main(int argc, char **argv) {
return 0;
}
catch (std::string err) {
std::cerr << "Error: " << err << std::endl;
std::cerr << "error: lsinc: " << err << std::endl;
}
return -1;

View File

@ -1,138 +0,0 @@
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
using namespace std::string_literals;
struct project_t {
std::string output;
std::vector<std::string> deps;
};
std::string read_str(std::istream &f, const std::string &skip_chars, const std::string &end_chars, int &end_char) {
std::vector<char> res {};
int c;
while (true) {
c = f.get();
auto a = end_chars.find(c);
if (c == -1 || a != std::string::npos) {
end_char = c;
return "";
}
if ((a = skip_chars.find(c)) == std::string::npos) {
f.unget();
break;
}
}
while (true) {
c = f.get();
if (c == -1 || end_chars.find(c) != std::string::npos) {
end_char = c;
break;
}
res.push_back(c);
}
while (true) {
if (skip_chars.find(res.back()) != std::string::npos) res.pop_back();
else break;
}
return std::string { res.begin(), res.end() };
}
std::string read_str(std::istream &f, const std::string &skip_chars, const std::string &end_chars) {
int end_char;
return read_str(f, skip_chars, end_chars, end_char);
}
project_t read_project(std::istream &f) {
int end_ch;
std::string name = read_str(f, " \v\t\r\n", "\n", end_ch);
std::vector<std::string> deps {};
if (name.length() == 0) {
throw "The name of a project may not be empty."s;
}
if (end_ch == -1) {
return project_t {
.output = name,
.deps = deps,
};
}
if (name.find(',') != std::string::npos || name.find(' ') != std::string::npos) {
throw "The name of a project may not contain spaces or commas."s;
}
while (true) {
std::string dep = read_str(f, " \v\t\r\n", ",\n", end_ch);
if (dep.find(' ') != std::string::npos) {
throw "The name of a dependency may not contain spaces."s;
}
if (dep.length()) {
deps.push_back(dep);
if (end_ch == '\n') break;
}
if (end_ch == -1) break;
}
return project_t {
.output = name,
.deps = deps,
};
}
void print_err(const std::string &error, const std::string &context) {
std::cerr << context << ": " << error;
}
int main(int argc, const char *argv[]) {
std::string proj_name = "";
try {
argc--;
argv++;
if (argc != 3) {
throw "Incorrect usage. Syntax: [src-dir] [project-name] [output|deps]."s;
}
std::string proj_path = (std::string) argv[0] + "/" + argv[1] + ".proj";
proj_name = argv[1];
std::ifstream f { proj_path, std::ios_base::in };
if (!f.is_open()) {
throw "The project '"s + argv[1] + "' doesn't exist."s;
}
project_t project = read_project(f);
f.close();
if ((std::string) argv[2] == "output") {
std::cout << project.output;
}
else if ((std::string) argv[2] == "deps") {
for (std::string dep : project.deps) {
std::cout << dep << " ";
}
}
else {
throw "Invalid command given. Available commands: output, deps."s;
}
std::cout << std::endl;
return 0;
}
catch (std::string err) {
if (proj_name.length()) std::cerr << "Error: " << proj_name << ": " << err << std::endl;
else std::cerr << "Error: " << err << std::endl;
}
return -1;
}

View File

@ -1,2 +0,0 @@
main
utils, treeifier, lang

View File

@ -1,2 +0,0 @@
treeifier
utils, lang

View File

@ -1 +0,0 @@
utils