Very raw version of nytl, no parsing yet

This commit is contained in:
Андреев Григорий 2024-08-12 19:43:35 +03:00
parent 5fab1131ca
commit be37e4f5ab
12 changed files with 236 additions and 97 deletions

View File

@ -11,6 +11,12 @@ namespace nytl {
template<typename T> template<typename T>
using uptr = std::unique_ptr<T>; using uptr = std::unique_ptr<T>;
template<typename Tp>
constexpr std::remove_reference_t<Tp>&&
mv(Tp&& t) noexcept
{ return static_cast<std::remove_reference_t<Tp>&&>(t); }
class FUp : public std::exception{ class FUp : public std::exception{
std::string WHAT; std::string WHAT;
public: public:

View File

@ -58,8 +58,8 @@ namespace nytl {
} else } else
assert(false); assert(false);
} }
while (true) {
const std::vector<json::JSON>& chain = expr["C"].g().asArray(); const std::vector<json::JSON>& chain = expr["C"].g().asArray();
while (true) {
if (chain_el >= chain.size()) if (chain_el >= chain.size())
return NULL; return NULL;
const json::JSON& t = chain[chain_el++]; const json::JSON& t = chain[chain_el++];
@ -79,9 +79,9 @@ namespace nytl {
while (!stack.empty()) { while (!stack.empty()) {
EEFrame& cur = *stack.back(); EEFrame& cur = *stack.back();
uptr<EEFrame> todo = cur.toMe(returned, global_elems, local_vars); uptr<EEFrame> todo = cur.toMe(returned, global_elems, local_vars);
returned = (bool)todo; returned = !(bool)todo;
if (todo) if (todo)
stack.push_back(todo); stack.push_back(mv(todo));
else else
stack.pop_back(); stack.pop_back();
} }

View File

@ -22,7 +22,7 @@ namespace nytl {
} }
void parse_bare_file(const std::string& filename, const std::string& content, void parse_bare_file(const std::string& filename, const std::string& content,
std::map<std::string, Element>& result) global_elem_set_t& result)
{ {
ASSERT(result.count(filename) == 0, "Repeated element " + filename); ASSERT(result.count(filename) == 0, "Repeated element " + filename);
std::vector<std::string> lines; std::vector<std::string> lines;
@ -66,23 +66,19 @@ namespace nytl {
} }
Element& el = result[filename]; Element& el = result[filename];
el.parts = {ElementPart{element_part_types::code}}; el.parts = {ElementPart{element_part_types::code}};
// std::string concatenated = "";
// el.parts[0].when_code.lines = std::move(lines);
std::string lines_cat; std::string lines_cat;
// todo: concatenate lines
size_t n = lines.size(); size_t n = lines.size();
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
lines_cat += lines[i]; lines_cat += lines[i];
if (i + 1 < n) if (i + 1 < n)
lines_cat += '\n'; lines_cat += '\n';
} }
json::JSON a; el.parts[0].when_code.lines = mv(lines_cat);
json::JSON b;
} }
void parse_special_file(const std::string& filename, const std::string& content, void parse_special_file(const std::string& filename, const std::string& content,
std::map<std::string, Element>& result) std::map<std::string, Element>& result)
{ {
// todo THROW("Don't know how to parse it yet");
} }
} }

View File

@ -9,21 +9,39 @@ namespace nytl {
std::string result; std::string result;
size_t cur_line_width = 0; size_t cur_line_width = 0;
void append(const std::string& text) { void append(const std::string& text, size_t wsp_before_newlines, bool& newlined_somewhere) {
size_t n = result.size(); size_t n = result.size();
result.resize(n + text.size()); size_t m = text.size();
memcpy((void*)&result.c_str()[n], text.c_str(), text.size()); result.reserve(n + m);
for (char ch: text) { for (size_t i = 0; i < m; i++) {
if (ch == '\n') if (text[i] == '\n') {
newlined_somewhere = true;
cur_line_width = 0; cur_line_width = 0;
else } else {
if (cur_line_width == 0 && newlined_somewhere) {
result.resize(result.size() + wsp_before_newlines, ' ');
cur_line_width = wsp_before_newlines;
}
cur_line_width++; cur_line_width++;
} }
result += text[i];
}
} }
}; };
#define RFrame_passed const global_elem_set_t& elem_ns, Ditch& result, const std::function<std::string(std::string)>& escape #define RFrame_passed const global_elem_set_t& elem_ns, Ditch& result, const std::function<std::string(std::string)>& escape
struct RFrame { struct RFrame {
size_t wsp_before_newlines = 0;
bool newlined_somewhere = false;
void append(const std::string& text, Ditch& ditch) {
ditch.append(text, wsp_before_newlines, newlined_somewhere);
}
explicit RFrame(size_t multiline_put_start)
: wsp_before_newlines(multiline_put_start) {
}
virtual uptr<RFrame> toMe(bool returned, RFrame_passed) {assert(false);} virtual uptr<RFrame> toMe(bool returned, RFrame_passed) {assert(false);}
virtual ~RFrame() = default; virtual ~RFrame() = default;
@ -33,18 +51,71 @@ namespace nytl {
std::string name; std::string name;
std::vector<LocalVarValue> passed_args; std::vector<LocalVarValue> passed_args;
/* This parameter incapsulates `cur_line_width` at some point for multiline `put-parts` */ /* This parameter incapsulates `cur_line_width` at some point for multiline `put-parts` */
size_t multiline_put_start = 0;
/* main iterator of this frame. Persistent across control returns */ /* main iterator of this frame. Persistent across control returns */
size_t part_to_do = 0; size_t part_to_do = 0;
RFrame_OverParts(const std::string &name, const std::vector<LocalVarValue>& passed_args, RFrame_OverParts(const std::string &name, const std::vector<LocalVarValue>& passed_args,
size_t multiline_put_start) size_t multiline_put_start)
: name(name), : RFrame(multiline_put_start), name(name),
passed_args(passed_args), passed_args(passed_args) {
multiline_put_start(multiline_put_start) {
} }
uptr<RFrame> toMe(bool returned, RFrame_passed) override { uptr<RFrame> toMe(bool returned, RFrame_passed) override;
};
struct RFrame_OverJSON: public RFrame {
const ElementPart::when_for_put_S& part;
/* During the course of iteration execution, given arg list will expand and shrink back */
std::vector<LocalVarValue> saved_args_plus_iter;
RFrame_OverJSON(const ElementPart::when_for_put_S &part, size_t multiline_put_start,
const std::vector<LocalVarValue> &saved_args)
: RFrame(multiline_put_start), part(part),
saved_args_plus_iter(saved_args) {
if (part.where_key_var > -1)
this->saved_args_plus_iter.emplace_back();
if (part.where_value_var > -1)
this->saved_args_plus_iter.emplace_back();
}
};
struct RFrame_OverArray : public RFrame_OverJSON {
const std::vector<json::JSON>& arr;
size_t it = 0;
/* Crutch. I can't pass simple integer as nytl local variable, I need persistent json wrapper */
json::JSON additional_json_wrapper;
RFrame_OverArray(const ElementPart::when_for_put_S& part, size_t multiline_put_start, const std::vector<LocalVarValue> &saved_args,
const std::vector<json::JSON> &arr): RFrame_OverJSON(part, multiline_put_start, saved_args),
arr(arr) {
if (part.where_key_var < 0)
additional_json_wrapper = json::JSON(json::Integer(0l));
}
uptr<RFrame> toMe(bool returned, const global_elem_set_t &elem_ns, Ditch &result,
const std::function<std::string(std::string)> &escape) override;
};
struct RFrame_OverDictionary: public RFrame_OverJSON {
const std::map<std::string, json::JSON>& dict;
std::map<std::string, json::JSON>::const_iterator it;
/* Crutch */
json::JSON addition_json_wrapper;
RFrame_OverDictionary(const ElementPart::when_for_put_S& part, size_t multiline_put_start, const std::vector<LocalVarValue> &saved_args_plus_iter,
const std::map<std::string, json::JSON> &dict): RFrame_OverJSON(part, multiline_put_start, saved_args_plus_iter),
dict(dict) {
it = dict.begin();
if (part.where_key_var < 0)
addition_json_wrapper = json::JSON("");
}
uptr<RFrame> toMe(bool returned, const global_elem_set_t &elem_ns, Ditch &result,
const std::function<std::string(std::string)> &escape) override;
};
uptr<RFrame> RFrame_OverParts::toMe(bool returned, const global_elem_set_t &elem_ns, Ditch &result,
const std::function<std::string(std::string)> &escape) {
if (!returned) if (!returned)
ASSERT(elem_ns.count(name) == 1, "No such element"); ASSERT(elem_ns.count(name) == 1, "No such element");
const Element& el = elem_ns.at(name); const Element& el = elem_ns.at(name);
@ -73,13 +144,13 @@ namespace nytl {
const json::JSON* X = passed_args[0].JSON_subval; const json::JSON* X = passed_args[0].JSON_subval;
assert(X); assert(X);
if (name == "jesc") { if (name == "jesc") {
result.append(escape(json::generate_str(*X, json::print_pretty))); append(escape(json::generate_str(*X, json::print_pretty)), result);
} else if (name == "str2text") { } else if (name == "str2text") {
ASSERT(X->isString(), "str2text takes json string"); ASSERT(X->isString(), "str2text takes json string");
result.append(escape(X->asString())); append(escape(X->asString()), result);
} else if (name == "str2code") { } else if (name == "str2code") {
ASSERT(X->isString(), "str2code takes json string"); ASSERT(X->isString(), "str2code takes json string");
result.append(X->asString()); append(X->asString(), result);
} }
return NULL; return NULL;
} }
@ -89,7 +160,7 @@ namespace nytl {
const ElementPart& cur_part = el.parts[part_to_do++]; const ElementPart& cur_part = el.parts[part_to_do++];
if (cur_part.type == element_part_types::code) { if (cur_part.type == element_part_types::code) {
const ElementPart::when_code_S& pt = cur_part.when_code; const ElementPart::when_code_S& pt = cur_part.when_code;
result.append(pt.lines); append(pt.lines, result);
} else if (cur_part.type == element_part_types::put) { } else if (cur_part.type == element_part_types::put) {
const ElementPart::when_put_S& pt = cur_part.when_put; const ElementPart::when_put_S& pt = cur_part.when_put;
LocalVarValue called_element_expv = rendering_core_execute_expression(elem_ns, passed_args, pt.called_element); LocalVarValue called_element_expv = rendering_core_execute_expression(elem_ns, passed_args, pt.called_element);
@ -98,17 +169,60 @@ namespace nytl {
std::vector<LocalVarValue> passed_arguments_expv(AN); std::vector<LocalVarValue> passed_arguments_expv(AN);
for (size_t i = 0; i < AN; i++) for (size_t i = 0; i < AN; i++)
passed_arguments_expv[i] = rendering_core_execute_expression(elem_ns, passed_args, pt.passed_arguments[i]); passed_arguments_expv[i] = rendering_core_execute_expression(elem_ns, passed_args, pt.passed_arguments[i]);
return uptr<RFrame>(new RFrame_OverParts(called_element_expv.EL_name, passed_arguments_expv, result.cur_line_width)); return std::make_unique<RFrame_OverParts>(called_element_expv.EL_name, passed_arguments_expv,
result.cur_line_width);
} else if (cur_part.type == element_part_types::for_put) { } else if (cur_part.type == element_part_types::for_put) {
const ElementPart::when_for_put_S& pt = cur_part.when_for_put; const ElementPart::when_for_put_S& pt = cur_part.when_for_put;
// todo LocalVarValue iting_over = rendering_core_execute_expression(elem_ns, passed_args, pt.ref_over);
ASSERT(iting_over.is_json, "Can't iterate over element");
const json::JSON& container = *iting_over.JSON_subval;
if (container.isArray()) {
return std::make_unique<RFrame_OverArray>(pt, result.cur_line_width, passed_args, container.asArray());
} else if (container.isDictionary()) {
return std::make_unique<RFrame_OverDictionary>(pt, result.cur_line_width, passed_args, container.asDictionary());
} else
THROW("Can't iterate over non-natalistic jsobject");
} else if (cur_part.type == element_part_types::ref_put) { } else if (cur_part.type == element_part_types::ref_put) {
const ElementPart::when_ref_put_S& pt = cur_part.when_ref_put; const ElementPart::when_ref_put_S& pt = cur_part.when_ref_put;
// todo std::vector<LocalVarValue> more_variables(passed_args.size() + 1);
std::copy(passed_args.begin(), passed_args.end(), more_variables.begin());
more_variables.back() = rendering_core_execute_expression(elem_ns, passed_args, pt.ref_over);
return std::make_unique<RFrame_OverParts>(pt.internal_element, more_variables, result.cur_line_width);
} }
} }
} }
};
uptr<RFrame> RFrame_OverArray::toMe(bool returned, RFrame_passed) {
if (returned && part.line_feed)
append("\n", result);
if (it >= arr.size())
return NULL;
if (part.where_key_var > -1) {
additional_json_wrapper.asInteger() = json::Integer((int64_t)it);
saved_args_plus_iter[part.where_key_var] = {true, "", &additional_json_wrapper};
}
if (part.where_value_var > -1) {
saved_args_plus_iter[part.where_value_var] = {true, "", &(arr[it])};
}
it++;
return std::make_unique<RFrame_OverParts>(part.internal_element, saved_args_plus_iter, wsp_before_newlines);
}
uptr<RFrame> RFrame_OverDictionary::toMe(bool returned, RFrame_passed) {
if (returned && part.line_feed)
append("\n", result);
if (it == dict.end())
return NULL;
if (part.where_key_var > -1) {
addition_json_wrapper.asString() = it->first;
saved_args_plus_iter[part.where_key_var] = {true, "", &addition_json_wrapper};
}
if (part.where_value_var > -1) {
saved_args_plus_iter[part.where_value_var] = {true, "", &it->second};
}
++it;
return std::make_unique<RFrame_OverParts>(part.internal_element, saved_args_plus_iter, wsp_before_newlines);
}
std::string rendering_core(const std::string& entry_func, const std::vector<json::JSON>& entry_arguments, std::string rendering_core(const std::string& entry_func, const std::vector<json::JSON>& entry_arguments,
const global_elem_set_t& elem_ns, const std::function<std::string(std::string)>& escape) const global_elem_set_t& elem_ns, const std::function<std::string(std::string)>& escape)
@ -122,13 +236,18 @@ namespace nytl {
std::vector<LocalVarValue> entry_arguments_conv(AN); std::vector<LocalVarValue> entry_arguments_conv(AN);
for (size_t i = 0; i < AN; i++) for (size_t i = 0; i < AN; i++)
entry_arguments_conv[i] = {true, "", &entry_arguments[i]}; entry_arguments_conv[i] = {true, "", &entry_arguments[i]};
// stack.push_back(std::make_unique<>()); stack.push_back(std::make_unique<RFrame_OverParts>(entry_func, entry_arguments_conv, 0));
// make_frame(entry_func, entry_arguments_conv);
} }
bool returned = false;
while (!stack.empty()) { while (!stack.empty()) {
// Frame& cur = *stack.back(); uptr<RFrame> ret = stack.back()->toMe(returned, elem_ns, result, escape);
returned = !(bool)ret;
if (ret)
stack.push_back(mv(ret));
else
stack.pop_back();
} }
assert(returned);
return result.result; return result.result;
} }
} }

View File

@ -38,7 +38,7 @@ namespace nytl {
std::vector<std::string> todo; std::vector<std::string> todo;
todo.emplace_back(); todo.emplace_back();
while (!todo.empty()) { while (!todo.empty()) {
std::string cur = std::move(todo.back()); std::string cur = mv(todo.back());
todo.pop_back(); todo.pop_back();
std::string path_to_cur_dir = rules.root_dir_path + "/" + cur; std::string path_to_cur_dir = rules.root_dir_path + "/" + cur;
DIR* D = opendir(path_to_cur_dir.c_str()); DIR* D = opendir(path_to_cur_dir.c_str());
@ -61,7 +61,7 @@ namespace nytl {
ASSERT_on_iret(ret, "stat(" + path_to_cur_child + ")"); ASSERT_on_iret(ret, "stat(" + path_to_cur_child + ")");
if (S_ISDIR(info.st_mode)) { if (S_ISDIR(info.st_mode)) {
if (isUname(child_entry)) if (isUname(child_entry))
todo.push_back(cur + "/" + child_entry); todo.push_back(cur.empty() ? child_entry : cur + "/" + child_entry);
} else if (S_ISREG(info.st_mode)) { } else if (S_ISREG(info.st_mode)) {
auto replace_sep = [](const std::string& slashed) -> std::string { auto replace_sep = [](const std::string& slashed) -> std::string {
std::string dotted; std::string dotted;
@ -76,7 +76,7 @@ namespace nytl {
}; };
auto np_reg_categ_result = [&](const std::string& no_postfix, bool applied) { auto np_reg_categ_result = [&](const std::string& no_postfix, bool applied) {
if (isUname(no_postfix)) if (isUname(no_postfix))
result.push_back({path_to_cur_child, replace_sep(cur + "/" + no_postfix), applied}); result.push_back({path_to_cur_child, replace_sep(cur.empty() ? no_postfix : cur + "/" + no_postfix), applied});
}; };
if (endsIn(child_entry, rules.postfix_rule_for_element_cont)) { if (endsIn(child_entry, rules.postfix_rule_for_element_cont)) {
np_reg_categ_result(throwout_postfix(child_entry, rules.postfix_rule_for_element_cont.size()), true); np_reg_categ_result(throwout_postfix(child_entry, rules.postfix_rule_for_element_cont.size()), true);

View File

@ -34,14 +34,14 @@ namespace nytl {
} when_put; } when_put;
struct when_for_put_S { struct when_for_put_S {
expression_t ref_over; expression_t ref_over;
bool have_av_key = false; ssize_t where_key_var = -1;
bool have_av_value = false; ssize_t where_value_var = -1;
expression_t internal_element; std::string internal_element;
bool line_feed = true; bool line_feed = true;
} when_for_put; } when_for_put;
struct when_ref_put_S { struct when_ref_put_S {
expression_t ref_over; expression_t ref_over;
expression_t internal_element; std::string internal_element;
} when_ref_put; } when_ref_put;
}; };

View File

@ -0,0 +1,17 @@
#include <new_york_transit_line/templater.h>
/* Yep, tests for nytl depend on assets for website. Yep, I see no problem with that */
int main(int argc, char** argv) {
if (argc < 2) {
fprintf(stderr, "Usage: test assets_dir");
exit(1);
}
std::string dir_path = argv[1];
nytl::Templater templater(nytl::TemplaterSettings{nytl::TemplaterDetourRules{dir_path}});
templater.update();
std::string answer = templater.render("chat", {});
printf("%s\n<a><f><t><e><r><><l><f>\n", answer.c_str());
return 0;
}

View File

@ -8,6 +8,7 @@
#include <jsonincpp/string_representation.h> #include <jsonincpp/string_representation.h>
#include <libregexis024vm/vm_opcodes.h> #include <libregexis024vm/vm_opcodes.h>
#include <engine_engine_number_9/form_data_structure/urlencoded_query.h> #include <engine_engine_number_9/form_data_structure/urlencoded_query.h>
#include <new_york_transit_line/templater.h>
bool termination = false; bool termination = false;
@ -54,7 +55,7 @@ int main(int argc, char** argv){
een9::StaticAssetManagerSlaveModule samI; een9::StaticAssetManagerSlaveModule samI;
samI.update({ samI.update({
een9::StaticAssetManagerRule{assets_dir + "/html", "/assets/html", {{".html", "text/html"}} }, een9::StaticAssetManagerRule{assets_dir + "/HypertextPages", "/assets/html", {{".html", "text/html"}} },
een9::StaticAssetManagerRule{assets_dir + "/css", "/assets/css", {{".css", "text/css"}} }, een9::StaticAssetManagerRule{assets_dir + "/css", "/assets/css", {{".css", "text/css"}} },
een9::StaticAssetManagerRule{assets_dir + "/js", "/assets/js", {{".js", "text/js"}} }, een9::StaticAssetManagerRule{assets_dir + "/js", "/assets/js", {{".js", "text/js"}} },
een9::StaticAssetManagerRule{assets_dir + "/img", "/assets/img", { een9::StaticAssetManagerRule{assets_dir + "/img", "/assets/img", {