initial
This commit is contained in:
28
td/tdtl/CMakeLists.txt
Normal file
28
td/tdtl/CMakeLists.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
if ((CMAKE_MAJOR_VERSION LESS 3) OR (CMAKE_VERSION VERSION_LESS "3.0.2"))
|
||||
message(FATAL_ERROR "CMake >= 3.0.2 is required")
|
||||
endif()
|
||||
|
||||
set(TDTL_SOURCE
|
||||
td/tl/tl_config.cpp
|
||||
td/tl/tl_core.cpp
|
||||
td/tl/tl_file_outputer.cpp
|
||||
td/tl/tl_file_utils.cpp
|
||||
td/tl/tl_generate.cpp
|
||||
td/tl/tl_outputer.cpp
|
||||
td/tl/tl_string_outputer.cpp
|
||||
td/tl/tl_writer.cpp
|
||||
|
||||
td/tl/tl_config.h
|
||||
td/tl/tl_core.h
|
||||
td/tl/tl_file_outputer.h
|
||||
td/tl/tl_file_utils.h
|
||||
td/tl/tl_generate.h
|
||||
td/tl/tl_outputer.h
|
||||
td/tl/tl_simple.h
|
||||
td/tl/tl_simple_parser.h
|
||||
td/tl/tl_string_outputer.h
|
||||
td/tl/tl_writer.h
|
||||
)
|
||||
|
||||
add_library(tdtl STATIC ${TDTL_SOURCE})
|
||||
target_include_directories(tdtl PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
||||
364
td/tdtl/td/tl/tl_config.cpp
Normal file
364
td/tdtl/td/tl/tl_config.cpp
Normal file
@@ -0,0 +1,364 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/tl/tl_config.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
const std::int32_t TLS_SCHEMA_V2 = 0x3a2f9be2;
|
||||
const std::int32_t TLS_SCHEMA_V3 = 0xe4a8604b;
|
||||
const std::int32_t TLS_SCHEMA_V4 = 0x90ac88d7;
|
||||
const std::int32_t TLS_TYPE = 0x12eb4386;
|
||||
const std::int32_t TLS_COMBINATOR = 0x5c0a1ed5;
|
||||
const std::int32_t TLS_COMBINATOR_LEFT_BUILTIN = 0xcd211f63;
|
||||
const std::int32_t TLS_COMBINATOR_LEFT = 0x4c12c6d9;
|
||||
const std::int32_t TLS_COMBINATOR_RIGHT_V2 = 0x2c064372;
|
||||
const std::int32_t TLS_ARG_V2 = 0x29dfe61b;
|
||||
|
||||
const std::int32_t TLS_EXPR_NAT = 0xdcb49bd8;
|
||||
const std::int32_t TLS_EXPR_TYPE = 0xecc9da78;
|
||||
|
||||
const std::int32_t TLS_NAT_CONST_OLD = 0xdcb49bd8;
|
||||
const std::int32_t TLS_NAT_CONST = 0x8ce940b1;
|
||||
const std::int32_t TLS_NAT_VAR = 0x4e8a14f0;
|
||||
const std::int32_t TLS_TYPE_VAR = 0x0142ceae;
|
||||
const std::int32_t TLS_ARRAY = 0xd9fb20de;
|
||||
const std::int32_t TLS_TYPE_EXPR = 0xc1863d08;
|
||||
|
||||
void tl_config::add_type(tl_type *type) {
|
||||
types.push_back(type);
|
||||
id_to_type[type->id] = type;
|
||||
name_to_type[type->name] = type;
|
||||
}
|
||||
|
||||
tl_type *tl_config::get_type(std::int32_t type_id) const {
|
||||
std::map<std::int32_t, tl_type *>::const_iterator it = id_to_type.find(type_id);
|
||||
assert(it != id_to_type.end());
|
||||
return it->second;
|
||||
}
|
||||
|
||||
tl_type *tl_config::get_type(const std::string &type_name) {
|
||||
return name_to_type[type_name];
|
||||
}
|
||||
|
||||
void tl_config::add_function(tl_combinator *function) {
|
||||
functions.push_back(function);
|
||||
id_to_function[function->id] = function;
|
||||
name_to_function[function->name] = function;
|
||||
}
|
||||
|
||||
tl_combinator *tl_config::get_function(std::int32_t function_id) {
|
||||
return id_to_function[function_id];
|
||||
}
|
||||
|
||||
tl_combinator *tl_config::get_function(const std::string &function_name) {
|
||||
return name_to_function[function_name];
|
||||
}
|
||||
|
||||
std::size_t tl_config::get_type_count() const {
|
||||
return types.size();
|
||||
}
|
||||
|
||||
tl_type *tl_config::get_type_by_num(std::size_t num) const {
|
||||
return types[num];
|
||||
}
|
||||
|
||||
std::size_t tl_config::get_function_count() const {
|
||||
return functions.size();
|
||||
}
|
||||
|
||||
tl_combinator *tl_config::get_function_by_num(std::size_t num) const {
|
||||
return functions[num];
|
||||
}
|
||||
|
||||
std::int32_t tl_config_parser::try_parse_int() {
|
||||
return try_parse(p.fetch_int());
|
||||
}
|
||||
|
||||
std::int64_t tl_config_parser::try_parse_long() {
|
||||
return try_parse(p.fetch_long());
|
||||
}
|
||||
|
||||
std::string tl_config_parser::try_parse_string() {
|
||||
return try_parse(p.fetch_string());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T tl_config_parser::try_parse(const T &res) const {
|
||||
if (p.get_error() != NULL) {
|
||||
std::fprintf(stderr, "Wrong TL-scheme specified: %s at %d\n", p.get_error(), static_cast<int>(p.get_error_pos()));
|
||||
std::abort();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int tl_config_parser::get_schema_version(std::int32_t version_id) {
|
||||
if (version_id == TLS_SCHEMA_V4) {
|
||||
return 4;
|
||||
}
|
||||
if (version_id == TLS_SCHEMA_V3) {
|
||||
return 3;
|
||||
}
|
||||
if (version_id == TLS_SCHEMA_V2) {
|
||||
return 2;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
tl_tree *tl_config_parser::read_num_const() {
|
||||
int num = static_cast<int>(try_parse_int());
|
||||
|
||||
return new tl_tree_nat_const(FLAG_NOVAR, num);
|
||||
}
|
||||
|
||||
tl_tree *tl_config_parser::read_num_var(int *var_count) {
|
||||
std::int32_t diff = try_parse_int();
|
||||
int var_num = static_cast<int>(try_parse_int());
|
||||
|
||||
if (var_num >= *var_count) {
|
||||
*var_count = var_num + 1;
|
||||
}
|
||||
|
||||
return new tl_tree_var_num(0, var_num, diff);
|
||||
}
|
||||
|
||||
tl_tree *tl_config_parser::read_type_var(int *var_count) {
|
||||
int var_num = static_cast<int>(try_parse_int());
|
||||
std::int32_t flags = try_parse_int();
|
||||
|
||||
if (var_num >= *var_count) {
|
||||
*var_count = var_num + 1;
|
||||
}
|
||||
assert(!(flags & (FLAG_NOVAR | FLAG_BARE)));
|
||||
|
||||
return new tl_tree_var_type(flags, var_num);
|
||||
}
|
||||
|
||||
tl_tree *tl_config_parser::read_array(int *var_count) {
|
||||
std::int32_t flags = FLAG_NOVAR;
|
||||
tl_tree *multiplicity = read_nat_expr(var_count);
|
||||
|
||||
tl_tree_array *T = new tl_tree_array(flags, multiplicity, read_args_list(var_count));
|
||||
|
||||
for (std::size_t i = 0; i < T->args.size(); i++) {
|
||||
if (!(T->args[i].flags & FLAG_NOVAR)) {
|
||||
T->flags &= ~FLAG_NOVAR;
|
||||
}
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
tl_tree *tl_config_parser::read_type(int *var_count) {
|
||||
tl_type *type = config.get_type(try_parse_int());
|
||||
assert(type != NULL);
|
||||
std::int32_t flags = try_parse_int() | FLAG_NOVAR;
|
||||
int arity = static_cast<int>(try_parse_int());
|
||||
assert(type->arity == arity);
|
||||
|
||||
tl_tree_type *T = new tl_tree_type(flags, type, arity);
|
||||
for (std::int32_t i = 0; i < arity; i++) {
|
||||
tl_tree *child = read_expr(var_count);
|
||||
|
||||
T->children[i] = child;
|
||||
if (!(child->flags & FLAG_NOVAR)) {
|
||||
T->flags &= ~FLAG_NOVAR;
|
||||
}
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
tl_tree *tl_config_parser::read_type_expr(int *var_count) {
|
||||
std::int32_t tree_type = try_parse_int();
|
||||
switch (tree_type) {
|
||||
case TLS_TYPE_VAR:
|
||||
return read_type_var(var_count);
|
||||
case TLS_TYPE_EXPR:
|
||||
return read_type(var_count);
|
||||
case TLS_ARRAY:
|
||||
return read_array(var_count);
|
||||
default:
|
||||
std::fprintf(stderr, "tree_type = %d\n", static_cast<int>(tree_type));
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
tl_tree *tl_config_parser::read_nat_expr(int *var_count) {
|
||||
std::int32_t tree_type = try_parse_int();
|
||||
switch (tree_type) {
|
||||
case TLS_NAT_CONST_OLD:
|
||||
case TLS_NAT_CONST:
|
||||
return read_num_const();
|
||||
case TLS_NAT_VAR:
|
||||
return read_num_var(var_count);
|
||||
default:
|
||||
std::fprintf(stderr, "tree_type = %d\n", static_cast<int>(tree_type));
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
tl_tree *tl_config_parser::read_expr(int *var_count) {
|
||||
std::int32_t tree_type = try_parse_int();
|
||||
switch (tree_type) {
|
||||
case TLS_EXPR_NAT:
|
||||
return read_nat_expr(var_count);
|
||||
case TLS_EXPR_TYPE:
|
||||
return read_type_expr(var_count);
|
||||
default:
|
||||
std::fprintf(stderr, "tree_type = %d\n", static_cast<int>(tree_type));
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<arg> tl_config_parser::read_args_list(int *var_count) {
|
||||
const int schema_flag_opt_field = 2 << static_cast<int>(schema_version >= 3);
|
||||
const int schema_flag_has_vars = schema_flag_opt_field ^ 6;
|
||||
|
||||
std::size_t args_num = static_cast<size_t>(try_parse_int());
|
||||
std::vector<arg> args(args_num);
|
||||
for (std::size_t i = 0; i < args_num; i++) {
|
||||
arg cur_arg;
|
||||
|
||||
std::int32_t arg_v = try_parse_int();
|
||||
if (arg_v != TLS_ARG_V2) {
|
||||
std::fprintf(stderr, "Wrong tls_arg magic %d\n", static_cast<int>(arg_v));
|
||||
std::abort();
|
||||
}
|
||||
|
||||
cur_arg.name = try_parse_string();
|
||||
cur_arg.flags = try_parse_int();
|
||||
|
||||
bool is_optional = false;
|
||||
if (cur_arg.flags & schema_flag_opt_field) {
|
||||
cur_arg.flags &= ~schema_flag_opt_field;
|
||||
is_optional = true;
|
||||
}
|
||||
if (cur_arg.flags & schema_flag_has_vars) {
|
||||
cur_arg.flags &= ~schema_flag_has_vars;
|
||||
cur_arg.var_num = static_cast<int>(try_parse_int());
|
||||
} else {
|
||||
cur_arg.var_num = -1;
|
||||
}
|
||||
|
||||
if (cur_arg.var_num >= *var_count) {
|
||||
*var_count = cur_arg.var_num + 1;
|
||||
}
|
||||
if (is_optional) {
|
||||
cur_arg.exist_var_num = static_cast<int>(try_parse_int());
|
||||
cur_arg.exist_var_bit = static_cast<int>(try_parse_int());
|
||||
} else {
|
||||
cur_arg.exist_var_num = -1;
|
||||
cur_arg.exist_var_bit = 0;
|
||||
}
|
||||
cur_arg.type = read_type_expr(var_count);
|
||||
if (/*cur_arg.var_num < 0 && cur_arg.exist_var_num < 0 && */ (cur_arg.type->flags & FLAG_NOVAR)) {
|
||||
cur_arg.flags |= FLAG_NOVAR;
|
||||
}
|
||||
|
||||
args[i] = cur_arg;
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
tl_combinator *tl_config_parser::read_combinator() {
|
||||
std::int32_t t = try_parse_int();
|
||||
if (t != TLS_COMBINATOR) {
|
||||
std::fprintf(stderr, "Wrong tls_combinator magic %d\n", static_cast<int>(t));
|
||||
std::abort();
|
||||
}
|
||||
|
||||
tl_combinator *combinator = new tl_combinator();
|
||||
combinator->id = try_parse_int();
|
||||
combinator->name = try_parse_string();
|
||||
combinator->type_id = try_parse_int();
|
||||
combinator->var_count = 0;
|
||||
|
||||
std::int32_t left_type = try_parse_int();
|
||||
if (left_type == TLS_COMBINATOR_LEFT) {
|
||||
combinator->args = read_args_list(&combinator->var_count);
|
||||
} else {
|
||||
if (left_type != TLS_COMBINATOR_LEFT_BUILTIN) {
|
||||
std::fprintf(stderr, "Wrong tls_combinator_left magic %d\n", static_cast<int>(left_type));
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
std::int32_t right_ver = try_parse_int();
|
||||
if (right_ver != TLS_COMBINATOR_RIGHT_V2) {
|
||||
std::fprintf(stderr, "Wrong tls_combinator_right magic %d\n", static_cast<int>(right_ver));
|
||||
std::abort();
|
||||
}
|
||||
combinator->result = read_type_expr(&combinator->var_count);
|
||||
|
||||
return combinator;
|
||||
}
|
||||
|
||||
tl_type *tl_config_parser::read_type() {
|
||||
std::int32_t t = try_parse_int();
|
||||
if (t != TLS_TYPE) {
|
||||
std::fprintf(stderr, "Wrong tls_type magic %d\n", t);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
tl_type *type = new tl_type();
|
||||
type->id = try_parse_int();
|
||||
type->name = try_parse_string();
|
||||
type->constructors_num = static_cast<std::size_t>(try_parse_int());
|
||||
type->constructors.reserve(type->constructors_num);
|
||||
type->flags = try_parse_int();
|
||||
type->flags &= ~(1 | 8 | 16 | 1024);
|
||||
if (type->flags != 0) {
|
||||
std::fprintf(stderr, "Type %s has non-zero flags: %d\n", type->name.c_str(), static_cast<int>(type->flags));
|
||||
}
|
||||
type->arity = static_cast<int>(try_parse_int());
|
||||
|
||||
try_parse_long(); // unused
|
||||
return type;
|
||||
}
|
||||
|
||||
tl_config tl_config_parser::parse_config() {
|
||||
schema_version = get_schema_version(try_parse_int());
|
||||
if (schema_version < 2) {
|
||||
std::fprintf(stderr, "Unsupported tl-schema version %d\n", static_cast<int>(schema_version));
|
||||
std::abort();
|
||||
}
|
||||
|
||||
try_parse_int(); // date
|
||||
try_parse_int(); // version
|
||||
|
||||
std::int32_t types_n = try_parse_int();
|
||||
std::size_t constructors_total = 0;
|
||||
for (std::int32_t i = 0; i < types_n; i++) {
|
||||
tl_type *type = read_type();
|
||||
config.add_type(type);
|
||||
constructors_total += type->constructors_num;
|
||||
}
|
||||
|
||||
std::int32_t constructors_n = try_parse_int();
|
||||
assert(static_cast<std::size_t>(constructors_n) == constructors_total);
|
||||
(void)constructors_total;
|
||||
for (std::int32_t i = 0; i < constructors_n; i++) {
|
||||
tl_combinator *constructor = read_combinator();
|
||||
config.get_type(constructor->type_id)->add_constructor(constructor);
|
||||
}
|
||||
|
||||
std::int32_t functions_n = try_parse_int();
|
||||
for (std::int32_t i = 0; i < functions_n; i++) {
|
||||
config.add_function(read_combinator());
|
||||
}
|
||||
p.fetch_end();
|
||||
try_parse(0);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
87
td/tdtl/td/tl/tl_config.h
Normal file
87
td/tdtl/td/tl/tl_config.h
Normal file
@@ -0,0 +1,87 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/tl/tl_core.h"
|
||||
#include "td/tl/tl_simple_parser.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
class tl_config {
|
||||
std::vector<tl_type *> types;
|
||||
std::map<std::int32_t, tl_type *> id_to_type;
|
||||
std::map<std::string, tl_type *> name_to_type;
|
||||
|
||||
std::vector<tl_combinator *> functions;
|
||||
std::map<std::int32_t, tl_combinator *> id_to_function;
|
||||
std::map<std::string, tl_combinator *> name_to_function;
|
||||
|
||||
public:
|
||||
void add_type(tl_type *type);
|
||||
|
||||
tl_type *get_type(std::int32_t type_id) const;
|
||||
|
||||
tl_type *get_type(const std::string &type_name);
|
||||
|
||||
void add_function(tl_combinator *function);
|
||||
|
||||
tl_combinator *get_function(std::int32_t function_id);
|
||||
|
||||
tl_combinator *get_function(const std::string &function_name);
|
||||
|
||||
std::size_t get_type_count() const;
|
||||
|
||||
tl_type *get_type_by_num(std::size_t num) const;
|
||||
|
||||
std::size_t get_function_count() const;
|
||||
|
||||
tl_combinator *get_function_by_num(std::size_t num) const;
|
||||
};
|
||||
|
||||
class tl_config_parser {
|
||||
tl_simple_parser p;
|
||||
int schema_version;
|
||||
tl_config config;
|
||||
|
||||
static int get_schema_version(std::int32_t version_id);
|
||||
|
||||
tl_tree *read_num_const();
|
||||
tl_tree *read_num_var(int *var_count);
|
||||
tl_tree *read_type_var(int *var_count);
|
||||
tl_tree *read_array(int *var_count);
|
||||
tl_tree *read_type(int *var_count);
|
||||
tl_tree *read_type_expr(int *var_count);
|
||||
tl_tree *read_nat_expr(int *var_count);
|
||||
tl_tree *read_expr(int *var_count);
|
||||
std::vector<arg> read_args_list(int *var_count);
|
||||
|
||||
tl_combinator *read_combinator();
|
||||
tl_type *read_type();
|
||||
|
||||
template <class T>
|
||||
T try_parse(const T &res) const;
|
||||
|
||||
std::int32_t try_parse_int();
|
||||
std::int64_t try_parse_long();
|
||||
std::string try_parse_string();
|
||||
|
||||
public:
|
||||
tl_config_parser(const char *s, std::size_t len) : p(s, len), schema_version(-1) {
|
||||
}
|
||||
|
||||
tl_config parse_config();
|
||||
};
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
21
td/tdtl/td/tl/tl_core.cpp
Normal file
21
td/tdtl/td/tl/tl_core.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/tl/tl_core.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
void tl_type::add_constructor(tl_combinator *new_constructor) {
|
||||
constructors.push_back(new_constructor);
|
||||
|
||||
assert(constructors.size() <= constructors_num);
|
||||
}
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
159
td/tdtl/td/tl/tl_core.h
Normal file
159
td/tdtl/td/tl/tl_core.h
Normal file
@@ -0,0 +1,159 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
const int NODE_TYPE_TYPE = 1;
|
||||
const int NODE_TYPE_NAT_CONST = 2;
|
||||
const int NODE_TYPE_VAR_TYPE = 3;
|
||||
const int NODE_TYPE_VAR_NUM = 4;
|
||||
const int NODE_TYPE_ARRAY = 5;
|
||||
|
||||
const std::int32_t ID_VAR_NUM = 0x70659eff;
|
||||
const std::int32_t ID_VAR_TYPE = 0x2cecf817;
|
||||
const std::int32_t ID_INT = 0xa8509bda;
|
||||
const std::int32_t ID_LONG = 0x22076cba;
|
||||
const std::int32_t ID_DOUBLE = 0x2210c154;
|
||||
const std::int32_t ID_STRING = 0xb5286e24;
|
||||
const std::int32_t ID_VECTOR = 0x1cb5c415;
|
||||
const std::int32_t ID_DICTIONARY = 0x1f4c618f;
|
||||
const std::int32_t ID_MAYBE_TRUE = 0x3f9c8ef8;
|
||||
const std::int32_t ID_MAYBE_FALSE = 0x27930a7b;
|
||||
const std::int32_t ID_BOOL_FALSE = 0xbc799737;
|
||||
const std::int32_t ID_BOOL_TRUE = 0x997275b5;
|
||||
|
||||
const std::int32_t FLAG_OPT_VAR = (1 << 17);
|
||||
const std::int32_t FLAG_EXCL = (1 << 18);
|
||||
const std::int32_t FLAG_NOVAR = (1 << 21);
|
||||
const std::int32_t FLAG_DEFAULT_CONSTRUCTOR = (1 << 25);
|
||||
const std::int32_t FLAG_BARE = (1 << 0);
|
||||
const std::int32_t FLAG_COMPLEX = (1 << 1);
|
||||
const std::int32_t FLAGS_MASK = ((1 << 16) - 1);
|
||||
|
||||
class tl_combinator;
|
||||
|
||||
class tl_tree;
|
||||
|
||||
class tl_type {
|
||||
public:
|
||||
std::int32_t id;
|
||||
std::string name;
|
||||
int arity;
|
||||
std::int32_t flags;
|
||||
int simple_constructors;
|
||||
std::size_t constructors_num;
|
||||
std::vector<tl_combinator *> constructors;
|
||||
|
||||
void add_constructor(tl_combinator *new_constructor);
|
||||
};
|
||||
|
||||
class arg {
|
||||
public:
|
||||
std::string name;
|
||||
std::int32_t flags;
|
||||
int var_num;
|
||||
int exist_var_num;
|
||||
int exist_var_bit;
|
||||
tl_tree *type;
|
||||
};
|
||||
|
||||
class tl_combinator {
|
||||
public:
|
||||
std::int32_t id;
|
||||
std::string name;
|
||||
int var_count;
|
||||
std::int32_t type_id;
|
||||
std::vector<arg> args;
|
||||
tl_tree *result;
|
||||
};
|
||||
|
||||
class tl_tree {
|
||||
public:
|
||||
std::int32_t flags;
|
||||
|
||||
explicit tl_tree(std::int32_t flags) : flags(flags) {
|
||||
}
|
||||
|
||||
virtual int get_type() const = 0;
|
||||
|
||||
virtual ~tl_tree() {
|
||||
}
|
||||
};
|
||||
|
||||
class tl_tree_type : public tl_tree {
|
||||
public:
|
||||
tl_type *type;
|
||||
std::vector<tl_tree *> children;
|
||||
|
||||
tl_tree_type(std::int32_t flags, tl_type *type, int child_count) : tl_tree(flags), type(type), children(child_count) {
|
||||
}
|
||||
|
||||
virtual int get_type() const {
|
||||
return NODE_TYPE_TYPE;
|
||||
}
|
||||
};
|
||||
|
||||
class tl_tree_nat_const : public tl_tree {
|
||||
public:
|
||||
int num;
|
||||
|
||||
tl_tree_nat_const(std::int32_t flags, int num) : tl_tree(flags), num(num) {
|
||||
}
|
||||
|
||||
virtual int get_type() const {
|
||||
return NODE_TYPE_NAT_CONST;
|
||||
}
|
||||
};
|
||||
|
||||
class tl_tree_var_type : public tl_tree {
|
||||
public:
|
||||
int var_num;
|
||||
|
||||
tl_tree_var_type(std::int32_t flags, int var_num) : tl_tree(flags), var_num(var_num) {
|
||||
}
|
||||
|
||||
virtual int get_type() const {
|
||||
return NODE_TYPE_VAR_TYPE;
|
||||
}
|
||||
};
|
||||
|
||||
class tl_tree_var_num : public tl_tree {
|
||||
public:
|
||||
int var_num;
|
||||
int diff;
|
||||
|
||||
tl_tree_var_num(std::int32_t flags, int var_num, int diff) : tl_tree(flags), var_num(var_num), diff(diff) {
|
||||
}
|
||||
|
||||
virtual int get_type() const {
|
||||
return NODE_TYPE_VAR_NUM;
|
||||
}
|
||||
};
|
||||
|
||||
class tl_tree_array : public tl_tree {
|
||||
public:
|
||||
tl_tree *multiplicity;
|
||||
std::vector<arg> args;
|
||||
|
||||
tl_tree_array(std::int32_t flags, tl_tree *multiplicity, const std::vector<arg> &a)
|
||||
: tl_tree(flags), multiplicity(multiplicity), args(a) {
|
||||
}
|
||||
|
||||
virtual int get_type() const {
|
||||
return NODE_TYPE_ARRAY;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
41
td/tdtl/td/tl/tl_file_outputer.cpp
Normal file
41
td/tdtl/td/tl/tl_file_outputer.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/tl/tl_file_outputer.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
void tl_file_outputer::append(const std::string &str) {
|
||||
assert(f != NULL);
|
||||
std::fprintf(f, "%s", str.c_str());
|
||||
}
|
||||
|
||||
tl_file_outputer::tl_file_outputer() : f(NULL) {
|
||||
}
|
||||
|
||||
void tl_file_outputer::close() {
|
||||
if (f) {
|
||||
std::fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
bool tl_file_outputer::open(const std::string &file_name) {
|
||||
close();
|
||||
|
||||
f = std::fopen(file_name.c_str(), "w");
|
||||
|
||||
return (f != NULL);
|
||||
}
|
||||
|
||||
tl_file_outputer::~tl_file_outputer() {
|
||||
close();
|
||||
}
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
33
td/tdtl/td/tl/tl_file_outputer.h
Normal file
33
td/tdtl/td/tl/tl_file_outputer.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/tl/tl_outputer.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
class tl_file_outputer : public tl_outputer {
|
||||
FILE *f;
|
||||
|
||||
void close();
|
||||
|
||||
public:
|
||||
tl_file_outputer();
|
||||
|
||||
bool open(const std::string &file_name);
|
||||
|
||||
virtual void append(const std::string &str);
|
||||
|
||||
virtual ~tl_file_outputer();
|
||||
};
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
104
td/tdtl/td/tl/tl_file_utils.cpp
Normal file
104
td/tdtl/td/tl/tl_file_utils.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/tl/tl_file_utils.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
std::string get_file_contents(const std::string &file_name) {
|
||||
FILE *f = std::fopen(file_name.c_str(), "rb");
|
||||
if (f == NULL) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
int fseek_res = std::fseek(f, 0, SEEK_END);
|
||||
if (fseek_res != 0) {
|
||||
std::fprintf(stderr, "Can't seek to the end of the file \"%s\"", file_name.c_str());
|
||||
std::abort();
|
||||
}
|
||||
long size_long = std::ftell(f);
|
||||
if (size_long < 0 || size_long >= (1 << 25)) {
|
||||
std::fprintf(stderr, "Wrong file \"%s\" has wrong size = %ld", file_name.c_str(), size_long);
|
||||
std::abort();
|
||||
}
|
||||
std::size_t size = static_cast<std::size_t>(size_long);
|
||||
|
||||
std::string result(size, ' ');
|
||||
if (size != 0) {
|
||||
std::rewind(f);
|
||||
std::size_t fread_res = std::fread(&result[0], size, 1, f);
|
||||
if (fread_res != 1) {
|
||||
std::fprintf(stderr, "Can't read file \"%s\"", file_name.c_str());
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
std::fclose(f);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool put_file_contents(const std::string &file_name, const std::string &contents, bool compare_documentation) {
|
||||
std::string old_file_contents = get_file_contents(file_name);
|
||||
if (!compare_documentation) {
|
||||
old_file_contents = remove_documentation(old_file_contents);
|
||||
}
|
||||
|
||||
if (old_file_contents == contents) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::fprintf(stderr, "Write file %s\n", file_name.c_str());
|
||||
|
||||
FILE *f = std::fopen(file_name.c_str(), "wb");
|
||||
if (f == NULL) {
|
||||
std::fprintf(stderr, "Can't open file \"%s\"\n", file_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t fwrite_res = std::fwrite(contents.c_str(), contents.size(), 1, f);
|
||||
if (fwrite_res != 1) {
|
||||
std::fclose(f);
|
||||
return false;
|
||||
}
|
||||
if (std::fclose(f) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string remove_documentation(const std::string &str) {
|
||||
std::size_t line_begin = 0;
|
||||
std::string result;
|
||||
bool inside_documentation = false;
|
||||
while (line_begin < str.size()) {
|
||||
std::size_t line_end = str.find('\n', line_begin);
|
||||
if (line_end == std::string::npos) {
|
||||
line_end = str.size() - 1;
|
||||
}
|
||||
std::string line = str.substr(line_begin, line_end - line_begin + 1);
|
||||
line_begin = line_end + 1;
|
||||
|
||||
std::size_t pos = line.find_first_not_of(' ');
|
||||
if (pos != std::string::npos && ((line[pos] == '/' && line[pos + 1] == '/' && line[pos + 2] == '/') ||
|
||||
(line[pos] == '/' && line[pos + 1] == '*' && line[pos + 2] == '*') ||
|
||||
(inside_documentation && line[pos] == '*'))) {
|
||||
inside_documentation = !(line[pos] == '/' && line[pos + 1] == '/' && line[pos + 2] == '/') &&
|
||||
!(line[pos] == '*' && line[pos + 1] == '/');
|
||||
continue;
|
||||
}
|
||||
|
||||
inside_documentation = false;
|
||||
result += line;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
21
td/tdtl/td/tl/tl_file_utils.h
Normal file
21
td/tdtl/td/tl/tl_file_utils.h
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
std::string get_file_contents(const std::string &file_name);
|
||||
|
||||
bool put_file_contents(const std::string &file_name, const std::string &contents, bool compare_documentation);
|
||||
|
||||
std::string remove_documentation(const std::string &str);
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
1017
td/tdtl/td/tl/tl_generate.cpp
Normal file
1017
td/tdtl/td/tl/tl_generate.cpp
Normal file
File diff suppressed because it is too large
Load Diff
28
td/tdtl/td/tl/tl_generate.h
Normal file
28
td/tdtl/td/tl/tl_generate.h
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/tl/tl_config.h"
|
||||
#include "td/tl/tl_outputer.h"
|
||||
#include "td/tl/tl_writer.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
void write_tl(const tl_config &config, tl_outputer &out, const TL_writer &w);
|
||||
|
||||
tl_config read_tl_config_from_file(const std::string &file_name);
|
||||
|
||||
bool write_tl_to_file(const tl_config &config, const std::string &file_name, const TL_writer &w);
|
||||
|
||||
bool write_tl_to_multiple_files(const tl_config &config, const std::string &file_name_prefix,
|
||||
const std::string &file_name_suffix, const TL_writer &w);
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
16
td/tdtl/td/tl/tl_outputer.cpp
Normal file
16
td/tdtl/td/tl/tl_outputer.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/tl/tl_outputer.h"
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
tl_outputer::~tl_outputer() {
|
||||
}
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
22
td/tdtl/td/tl/tl_outputer.h
Normal file
22
td/tdtl/td/tl/tl_outputer.h
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
class tl_outputer {
|
||||
public:
|
||||
virtual void append(const std::string &str) = 0;
|
||||
|
||||
virtual ~tl_outputer() = 0;
|
||||
};
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
256
td/tdtl/td/tl/tl_simple.h
Normal file
256
td/tdtl/td/tl/tl_simple.h
Normal file
@@ -0,0 +1,256 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/tl/tl_config.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
namespace simple {
|
||||
|
||||
inline std::string gen_cpp_name(std::string name) {
|
||||
for (auto &c : name) {
|
||||
if ((c < '0' || '9' < c) && (c < 'a' || 'z' < c) && (c < 'A' || 'Z' < c)) {
|
||||
c = '_';
|
||||
}
|
||||
}
|
||||
assert(!name.empty());
|
||||
assert(name[name.size() - 1] != '_');
|
||||
return name;
|
||||
}
|
||||
|
||||
inline std::string gen_cpp_field_name(std::string name) {
|
||||
return gen_cpp_name(name) + '_';
|
||||
}
|
||||
|
||||
struct CustomType;
|
||||
struct Type {
|
||||
enum { Int32, Int53, Int64, Double, String, Bytes, Vector, Bool, Custom } type;
|
||||
|
||||
// type == Custom
|
||||
bool is_bare{false};
|
||||
const CustomType *custom{nullptr};
|
||||
|
||||
// type == Vector
|
||||
const Type *vector_value_type{nullptr};
|
||||
};
|
||||
|
||||
struct Arg {
|
||||
const Type *type;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct Constructor {
|
||||
std::string name;
|
||||
std::int32_t id;
|
||||
std::vector<Arg> args;
|
||||
const CustomType *type;
|
||||
};
|
||||
|
||||
struct CustomType {
|
||||
std::string name;
|
||||
std::vector<const Constructor *> constructors;
|
||||
|
||||
mutable bool is_result_{false};
|
||||
mutable bool is_query_{false};
|
||||
};
|
||||
|
||||
struct Function {
|
||||
std::string name;
|
||||
std::int32_t id;
|
||||
std::vector<Arg> args;
|
||||
const Type *type;
|
||||
};
|
||||
|
||||
class Schema {
|
||||
public:
|
||||
explicit Schema(const tl_config &config) {
|
||||
config_ = &config;
|
||||
for (std::size_t type_num = 0, type_count = config.get_type_count(); type_num < type_count; type_num++) {
|
||||
auto *from_type = config.get_type_by_num(type_num);
|
||||
if (from_type->name == "Vector") {
|
||||
continue;
|
||||
}
|
||||
auto *type = get_type(from_type);
|
||||
if (type->type == Type::Custom) {
|
||||
custom_types.push_back(type->custom);
|
||||
}
|
||||
}
|
||||
for (std::size_t function_num = 0, function_count = config.get_function_count(); function_num < function_count;
|
||||
function_num++) {
|
||||
auto *from_function = config.get_function_by_num(function_num);
|
||||
functions.push_back(get_function(from_function));
|
||||
}
|
||||
for (auto &function : functions_) {
|
||||
mark_result(function->type);
|
||||
for (auto &arg : function->args) {
|
||||
mark_query(arg.type);
|
||||
}
|
||||
}
|
||||
|
||||
//for (auto custom_type : custom_types) {
|
||||
//std::cerr << custom_type->name;
|
||||
//if (custom_type->is_result_) {
|
||||
//std::cerr << " result";
|
||||
//}
|
||||
//if (custom_type->is_query_) {
|
||||
//std::cerr << " query";
|
||||
//}
|
||||
//std::cerr << std::endl;
|
||||
//}
|
||||
}
|
||||
|
||||
std::vector<const CustomType *> custom_types;
|
||||
std::vector<const Function *> functions;
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<Function>> functions_;
|
||||
std::vector<std::unique_ptr<Constructor>> constructors_;
|
||||
std::vector<std::unique_ptr<CustomType>> custom_types_;
|
||||
std::vector<std::unique_ptr<Type>> types_;
|
||||
|
||||
const tl_config *config_{nullptr};
|
||||
std::map<std::int32_t, Type *> type_by_id;
|
||||
std::map<std::int32_t, Constructor *> constructor_by_id;
|
||||
std::map<std::int32_t, Function *> function_by_id;
|
||||
|
||||
void mark_result(const Type *type) {
|
||||
do_mark(type, true);
|
||||
}
|
||||
|
||||
void mark_query(const Type *type) {
|
||||
do_mark(type, false);
|
||||
}
|
||||
|
||||
void do_mark(const Type *type, bool is_result) {
|
||||
if (type->type == Type::Vector) {
|
||||
return do_mark(type->vector_value_type, is_result);
|
||||
}
|
||||
if (type->type != Type::Custom) {
|
||||
return;
|
||||
}
|
||||
auto *custom = type->custom;
|
||||
auto &was = is_result ? custom->is_result_ : custom->is_query_;
|
||||
if (was) {
|
||||
return;
|
||||
}
|
||||
was = true;
|
||||
for (auto constructor : custom->constructors) {
|
||||
for (auto &arg : constructor->args) {
|
||||
do_mark(arg.type, is_result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Type *get_type(const tl_type *from_type) {
|
||||
auto &type = type_by_id[from_type->id];
|
||||
if (!type) {
|
||||
types_.push_back(std::make_unique<Type>());
|
||||
type = types_.back().get();
|
||||
|
||||
if (from_type->name == "Int32") {
|
||||
type->type = Type::Int32;
|
||||
} else if (from_type->name == "Int53") {
|
||||
type->type = Type::Int53;
|
||||
} else if (from_type->name == "Int64") {
|
||||
type->type = Type::Int64;
|
||||
} else if (from_type->name == "Double") {
|
||||
type->type = Type::Double;
|
||||
} else if (from_type->name == "String") {
|
||||
type->type = Type::String;
|
||||
} else if (from_type->name == "Bytes") {
|
||||
type->type = Type::Bytes;
|
||||
} else if (from_type->name == "Bool") {
|
||||
type->type = Type::Bool;
|
||||
} else if (from_type->name == "Vector") {
|
||||
assert(false); // unreachable
|
||||
} else {
|
||||
type->type = Type::Custom;
|
||||
custom_types_.push_back(std::make_unique<CustomType>());
|
||||
auto *custom_type = custom_types_.back().get();
|
||||
type->custom = custom_type;
|
||||
custom_type->name = from_type->name;
|
||||
for (auto *constructor : from_type->constructors) {
|
||||
custom_type->constructors.push_back(get_constructor(constructor));
|
||||
}
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
const CustomType *get_custom_type(const tl_type *from_type) {
|
||||
auto *type = get_type(from_type);
|
||||
assert(type->type == Type::Custom);
|
||||
return type->custom;
|
||||
}
|
||||
|
||||
const Constructor *get_constructor(const tl_combinator *from) {
|
||||
auto &constructor = constructor_by_id[from->id];
|
||||
if (!constructor) {
|
||||
constructors_.push_back(std::make_unique<Constructor>());
|
||||
constructor = constructors_.back().get();
|
||||
constructor->id = from->id;
|
||||
constructor->name = from->name;
|
||||
constructor->type = get_custom_type(config_->get_type(from->type_id));
|
||||
for (auto &from_arg : from->args) {
|
||||
Arg arg;
|
||||
arg.name = from_arg.name;
|
||||
arg.type = get_type(from_arg.type);
|
||||
constructor->args.push_back(std::move(arg));
|
||||
}
|
||||
}
|
||||
return constructor;
|
||||
}
|
||||
|
||||
const Function *get_function(const tl_combinator *from) {
|
||||
auto &function = function_by_id[from->id];
|
||||
if (!function) {
|
||||
functions_.push_back(std::make_unique<Function>());
|
||||
function = functions_.back().get();
|
||||
function->id = from->id;
|
||||
function->name = from->name;
|
||||
function->type = get_type(config_->get_type(from->type_id));
|
||||
for (auto &from_arg : from->args) {
|
||||
Arg arg;
|
||||
arg.name = from_arg.name;
|
||||
arg.type = get_type(from_arg.type);
|
||||
function->args.push_back(std::move(arg));
|
||||
}
|
||||
}
|
||||
return function;
|
||||
}
|
||||
|
||||
const Type *get_type(const tl_tree *tree) {
|
||||
assert(tree->get_type() == NODE_TYPE_TYPE);
|
||||
auto *type_tree = static_cast<const tl_tree_type *>(tree);
|
||||
if (type_tree->type->name == "Vector") {
|
||||
assert(type_tree->children.size() == 1);
|
||||
types_.push_back(std::make_unique<Type>());
|
||||
auto *type = types_.back().get();
|
||||
type->type = Type::Vector;
|
||||
type->vector_value_type = get_type(type_tree->children[0]);
|
||||
return type;
|
||||
} else {
|
||||
assert(type_tree->children.empty());
|
||||
return get_type(type_tree->type);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace simple
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
107
td/tdtl/td/tl/tl_simple_parser.h
Normal file
107
td/tdtl/td/tl/tl_simple_parser.h
Normal file
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
class tl_simple_parser {
|
||||
const char *data;
|
||||
const char *data_begin;
|
||||
std::size_t data_len;
|
||||
const char *error;
|
||||
std::size_t error_pos;
|
||||
|
||||
void set_error(const char *error_message) {
|
||||
if (error == NULL) {
|
||||
assert(error_message != NULL);
|
||||
error = error_message;
|
||||
error_pos = static_cast<std::size_t>(data - data_begin);
|
||||
data = "\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
data_len = 0;
|
||||
} else {
|
||||
data = "\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
assert(data_len == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void check_len(const std::size_t len) {
|
||||
if (data_len < len) {
|
||||
set_error("Not enough data to read");
|
||||
} else {
|
||||
data_len -= len;
|
||||
}
|
||||
}
|
||||
|
||||
tl_simple_parser(const tl_simple_parser &other);
|
||||
tl_simple_parser &operator=(const tl_simple_parser &other);
|
||||
|
||||
public:
|
||||
tl_simple_parser(const char *data, std::size_t data_len)
|
||||
: data(data), data_begin(data), data_len(data_len), error(), error_pos() {
|
||||
}
|
||||
|
||||
const char *get_error() const {
|
||||
return error;
|
||||
}
|
||||
|
||||
std::size_t get_error_pos() const {
|
||||
return error_pos;
|
||||
}
|
||||
|
||||
std::int32_t fetch_int() {
|
||||
check_len(sizeof(std::int32_t));
|
||||
std::int32_t result = *reinterpret_cast<const std::int32_t *>(data);
|
||||
data += sizeof(std::int32_t);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::int64_t fetch_long() {
|
||||
check_len(sizeof(std::int64_t));
|
||||
std::int64_t result;
|
||||
std::memcpy(&result, data, sizeof(std::int64_t));
|
||||
data += sizeof(std::int64_t);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string fetch_string() {
|
||||
check_len(4);
|
||||
int result_len = static_cast<unsigned char>(data[0]);
|
||||
if (result_len < 254) {
|
||||
check_len((result_len >> 2) * 4);
|
||||
std::string result(data + 1, result_len);
|
||||
data += ((result_len >> 2) + 1) * 4;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (result_len == 254) {
|
||||
result_len = static_cast<unsigned char>(data[1]) + (static_cast<unsigned char>(data[2]) << 8) +
|
||||
(static_cast<unsigned char>(data[3]) << 16);
|
||||
check_len(((result_len + 3) >> 2) * 4);
|
||||
std::string result(data + 4, result_len);
|
||||
data += ((result_len + 7) >> 2) * 4;
|
||||
return result;
|
||||
}
|
||||
|
||||
set_error("Can't fetch string, 255 found");
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void fetch_end() {
|
||||
if (data_len) {
|
||||
set_error("Too much data to fetch");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
32
td/tdtl/td/tl/tl_string_outputer.cpp
Normal file
32
td/tdtl/td/tl/tl_string_outputer.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/tl/tl_string_outputer.h"
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
void tl_string_outputer::append(const std::string &str) {
|
||||
result += str;
|
||||
}
|
||||
|
||||
std::string tl_string_outputer::get_result() const {
|
||||
#if defined(_WIN32)
|
||||
std::string fixed_result;
|
||||
for (std::size_t i = 0; i < result.size(); i++) {
|
||||
if (result[i] == '\n') {
|
||||
fixed_result += '\r';
|
||||
}
|
||||
fixed_result += result[i];
|
||||
}
|
||||
return fixed_result;
|
||||
#else
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
26
td/tdtl/td/tl/tl_string_outputer.h
Normal file
26
td/tdtl/td/tl/tl_string_outputer.h
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/tl/tl_outputer.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
class tl_string_outputer : public tl_outputer {
|
||||
std::string result;
|
||||
|
||||
public:
|
||||
virtual void append(const std::string &str);
|
||||
|
||||
std::string get_result() const;
|
||||
};
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
239
td/tdtl/td/tl/tl_writer.cpp
Normal file
239
td/tdtl/td/tl/tl_writer.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/tl/tl_writer.h"
|
||||
|
||||
#include "td/tl/tl_core.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
std::string TL_writer::int_to_string(int x) {
|
||||
char buf[15];
|
||||
std::snprintf(buf, sizeof(buf), "%d", x);
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool TL_writer::is_alnum(char c) {
|
||||
return ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
|
||||
}
|
||||
|
||||
char TL_writer::to_lower(char c) {
|
||||
return 'A' <= c && c <= 'Z' ? static_cast<char>(c - 'A' + 'a') : c;
|
||||
}
|
||||
|
||||
char TL_writer::to_upper(char c) {
|
||||
return 'a' <= c && c <= 'z' ? static_cast<char>(c - 'a' + 'A') : c;
|
||||
}
|
||||
|
||||
std::vector<std::string> TL_writer::get_additional_functions() const {
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
bool TL_writer::is_type_supported(const tl_tree_type *tree_type) const {
|
||||
if (tree_type->type->flags & FLAG_COMPLEX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < tree_type->children.size(); i++) {
|
||||
const tl_tree *child = tree_type->children[i];
|
||||
assert(child->get_type() == NODE_TYPE_TYPE || child->get_type() == NODE_TYPE_VAR_TYPE ||
|
||||
child->get_type() == NODE_TYPE_NAT_CONST || child->get_type() == NODE_TYPE_VAR_NUM);
|
||||
|
||||
if (child->get_type() == NODE_TYPE_TYPE) {
|
||||
if (!is_type_supported(static_cast<const tl_tree_type *>(child))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (child->get_type() == NODE_TYPE_VAR_TYPE) {
|
||||
return false; // TODO
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TL_writer::is_combinator_supported(const tl_combinator *constructor) const {
|
||||
std::vector<bool> is_function_result(constructor->var_count);
|
||||
for (std::size_t i = 0; i < constructor->args.size(); i++) {
|
||||
const arg &a = constructor->args[i];
|
||||
|
||||
int arg_type = a.type->get_type();
|
||||
if (arg_type == NODE_TYPE_VAR_TYPE) {
|
||||
const tl_tree_var_type *t = static_cast<const tl_tree_var_type *>(a.type);
|
||||
if (a.flags & FLAG_EXCL) {
|
||||
assert(t->var_num >= 0);
|
||||
if (is_function_result[t->var_num]) {
|
||||
return false; // lazy to check that results of two function calls are the same
|
||||
}
|
||||
is_function_result[t->var_num] = true;
|
||||
} else {
|
||||
return false; // do not support generic types
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < constructor->args.size(); i++) {
|
||||
const arg &a = constructor->args[i];
|
||||
|
||||
int arg_type = a.type->get_type();
|
||||
if (a.var_num >= 0) {
|
||||
assert(arg_type == NODE_TYPE_TYPE);
|
||||
const tl_tree_type *a_type = static_cast<const tl_tree_type *>(a.type);
|
||||
if (a_type->type->id == ID_VAR_TYPE) {
|
||||
assert(!(a_type->flags & FLAG_EXCL));
|
||||
if (!is_function_result[a.var_num]) {
|
||||
assert(false); // not possible, otherwise type is an argument of a type, but all types with type arguments
|
||||
// are already marked complex
|
||||
return false;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_type == NODE_TYPE_VAR_TYPE) {
|
||||
continue;
|
||||
} else if (arg_type == NODE_TYPE_TYPE) {
|
||||
if (!is_type_supported(static_cast<const tl_tree_type *>(a.type))) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
assert(arg_type == NODE_TYPE_ARRAY);
|
||||
const tl_tree_array *arr = static_cast<const tl_tree_array *>(a.type);
|
||||
for (std::size_t j = 0; j < arr->args.size(); j++) {
|
||||
const arg &b = arr->args[j];
|
||||
assert(b.type->get_type() == NODE_TYPE_TYPE && b.var_num == -1);
|
||||
if (!is_type_supported(static_cast<const tl_tree_type *>(b.type))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tl_tree *result = constructor->result;
|
||||
if (result->get_type() == NODE_TYPE_TYPE) {
|
||||
if (!is_type_supported(static_cast<const tl_tree_type *>(result))) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
assert(result->get_type() == NODE_TYPE_VAR_TYPE);
|
||||
const tl_tree_var_type *t = static_cast<const tl_tree_var_type *>(result);
|
||||
return is_function_result[t->var_num];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TL_writer::is_documentation_generated() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TL_writer::is_default_constructor_generated(const tl_combinator *t, bool can_be_parsed, bool can_be_stored) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TL_writer::is_full_constructor_generated(const tl_combinator *t, bool can_be_parsed, bool can_be_stored) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string TL_writer::gen_main_class_name(const tl_type *t) const {
|
||||
if (t->simple_constructors == 1) {
|
||||
for (std::size_t i = 0; i < t->constructors_num; i++) {
|
||||
if (is_combinator_supported(t->constructors[i])) {
|
||||
return gen_class_name(t->constructors[i]->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return gen_class_name(t->name);
|
||||
}
|
||||
|
||||
int TL_writer::get_parser_type(const tl_combinator *t, const std::string &parser_name) const {
|
||||
return t->var_count > 0;
|
||||
}
|
||||
|
||||
int TL_writer::get_storer_type(const tl_combinator *t, const std::string &storer_name) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TL_writer::get_additional_function_type(const std::string &additional_function_name) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TL_writer::Mode TL_writer::get_parser_mode(int type) const {
|
||||
return All;
|
||||
}
|
||||
|
||||
TL_writer::Mode TL_writer::get_storer_mode(int type) const {
|
||||
return All;
|
||||
}
|
||||
|
||||
std::string TL_writer::gen_field_type(const arg &a) const {
|
||||
if (a.flags & FLAG_EXCL) {
|
||||
assert(a.flags == FLAG_EXCL);
|
||||
assert(a.type->get_type() == NODE_TYPE_VAR_TYPE);
|
||||
|
||||
return gen_var_type_name();
|
||||
}
|
||||
|
||||
assert(a.flags == FLAG_NOVAR || a.flags == 0 || a.flags == (FLAG_OPT_VAR | FLAG_NOVAR | FLAG_BARE));
|
||||
|
||||
if (a.type->get_type() == NODE_TYPE_TYPE) {
|
||||
const tl_tree_type *arg_type = static_cast<const tl_tree_type *>(a.type);
|
||||
assert(arg_type->children.size() == static_cast<std::size_t>(arg_type->type->arity));
|
||||
|
||||
if (arg_type->type->id == ID_VAR_TYPE) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return gen_type_name(arg_type);
|
||||
} else {
|
||||
assert(a.flags == FLAG_NOVAR || a.flags == 0);
|
||||
|
||||
assert(a.type->get_type() == NODE_TYPE_ARRAY);
|
||||
const tl_tree_array *arg_array = static_cast<const tl_tree_array *>(a.type);
|
||||
assert((arg_array->flags & ~FLAG_NOVAR) == 0);
|
||||
return gen_array_type_name(arg_array, a.name);
|
||||
}
|
||||
}
|
||||
|
||||
std::string TL_writer::gen_additional_function(const std::string &function_name, const tl_combinator *t,
|
||||
bool is_function) const {
|
||||
assert(false);
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string TL_writer::gen_additional_proxy_function_begin(const std::string &function_name, const tl_type *type,
|
||||
const std::string &class_name, int arity,
|
||||
bool is_function) const {
|
||||
assert(false);
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string TL_writer::gen_additional_proxy_function_case(const std::string &function_name, const tl_type *type,
|
||||
const std::string &class_name, int arity) const {
|
||||
assert(false);
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string TL_writer::gen_additional_proxy_function_case(const std::string &function_name, const tl_type *type,
|
||||
const tl_combinator *t, int arity, bool is_function) const {
|
||||
assert(false);
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string TL_writer::gen_additional_proxy_function_end(const std::string &function_name, const tl_type *type,
|
||||
bool is_function) const {
|
||||
assert(false);
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
169
td/tdtl/td/tl/tl_writer.h
Normal file
169
td/tdtl/td/tl/tl_writer.h
Normal file
@@ -0,0 +1,169 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/tl/tl_core.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
class var_description {
|
||||
public:
|
||||
int index;
|
||||
bool is_stored;
|
||||
bool is_type;
|
||||
int parameter_num;
|
||||
int function_arg_num;
|
||||
|
||||
var_description() : index(-1), is_stored(false), is_type(false), parameter_num(-1), function_arg_num(-1) {
|
||||
}
|
||||
};
|
||||
|
||||
class TL_writer {
|
||||
TL_writer(const TL_writer &other);
|
||||
TL_writer &operator=(const TL_writer &other);
|
||||
|
||||
protected:
|
||||
const std::string tl_name;
|
||||
|
||||
public:
|
||||
enum Mode { All, Client, Server };
|
||||
|
||||
explicit TL_writer(const std::string &tl_name) : tl_name(tl_name) {
|
||||
}
|
||||
|
||||
virtual ~TL_writer() {
|
||||
}
|
||||
|
||||
virtual int get_max_arity() const = 0;
|
||||
|
||||
static std::string int_to_string(int x);
|
||||
static bool is_alnum(char c);
|
||||
static char to_lower(char c);
|
||||
static char to_upper(char c);
|
||||
|
||||
virtual bool is_built_in_simple_type(const std::string &name) const = 0;
|
||||
virtual bool is_built_in_complex_type(const std::string &name) const = 0;
|
||||
virtual bool is_type_supported(const tl_tree_type *tree_type) const;
|
||||
virtual bool is_type_bare(const tl_type *t) const = 0;
|
||||
virtual bool is_combinator_supported(const tl_combinator *constructor) const;
|
||||
virtual bool is_documentation_generated() const;
|
||||
virtual bool is_default_constructor_generated(const tl_combinator *t, bool can_be_parsed, bool can_be_stored) const;
|
||||
virtual bool is_full_constructor_generated(const tl_combinator *t, bool can_be_parsed, bool can_be_stored) const;
|
||||
|
||||
virtual int get_parser_type(const tl_combinator *t, const std::string &parser_name) const;
|
||||
virtual int get_storer_type(const tl_combinator *t, const std::string &storer_name) const;
|
||||
virtual int get_additional_function_type(const std::string &additional_function_name) const;
|
||||
virtual Mode get_parser_mode(int type) const;
|
||||
virtual Mode get_storer_mode(int type) const;
|
||||
virtual std::vector<std::string> get_parsers() const = 0;
|
||||
virtual std::vector<std::string> get_storers() const = 0;
|
||||
virtual std::vector<std::string> get_additional_functions() const;
|
||||
|
||||
virtual std::string gen_base_tl_class_name() const = 0;
|
||||
virtual std::string gen_base_type_class_name(int arity) const = 0;
|
||||
virtual std::string gen_base_function_class_name() const = 0;
|
||||
virtual std::string gen_class_name(std::string name) const = 0;
|
||||
virtual std::string gen_field_name(std::string name) const = 0;
|
||||
virtual std::string gen_var_name(const var_description &desc) const = 0;
|
||||
virtual std::string gen_parameter_name(int index) const = 0;
|
||||
virtual std::string gen_main_class_name(const tl_type *t) const;
|
||||
virtual std::string gen_field_type(const arg &a) const;
|
||||
virtual std::string gen_type_name(const tl_tree_type *tree_type) const = 0;
|
||||
virtual std::string gen_array_type_name(const tl_tree_array *arr, const std::string &field_name) const = 0;
|
||||
virtual std::string gen_var_type_name() const = 0;
|
||||
|
||||
virtual std::string gen_int_const(const tl_tree *tree_c, const std::vector<var_description> &vars) const = 0;
|
||||
|
||||
virtual std::string gen_output_begin(const std::string &additional_imports) const = 0;
|
||||
virtual std::string gen_output_begin_once() const = 0;
|
||||
virtual std::string gen_output_end() const = 0;
|
||||
|
||||
virtual std::string gen_import_declaration(const std::string &name, bool is_system) const = 0;
|
||||
virtual std::string gen_package_suffix() const = 0;
|
||||
|
||||
virtual std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const = 0;
|
||||
|
||||
virtual std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name, bool is_proxy,
|
||||
const tl_tree *result) const = 0;
|
||||
virtual std::string gen_class_end() const = 0;
|
||||
|
||||
virtual std::string gen_class_alias(const std::string &class_name, const std::string &alias_name) const = 0;
|
||||
|
||||
virtual std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
|
||||
const std::string &field_name) const = 0;
|
||||
virtual std::string gen_flags_definitions(const tl_combinator *t, bool can_be_stored) const {
|
||||
return "";
|
||||
}
|
||||
|
||||
virtual std::string gen_vars(const tl_combinator *t, const tl_tree_type *result_type,
|
||||
std::vector<var_description> &vars) const = 0;
|
||||
virtual std::string gen_function_vars(const tl_combinator *t, std::vector<var_description> &vars) const = 0;
|
||||
virtual std::string gen_uni(const tl_tree_type *result_type, std::vector<var_description> &vars,
|
||||
bool check_negative) const = 0;
|
||||
virtual std::string gen_constructor_id_store(std::int32_t id, int storer_type) const = 0;
|
||||
virtual std::string gen_field_fetch(int field_num, const arg &a, std::vector<var_description> &vars, bool flat,
|
||||
int parser_type) const = 0;
|
||||
virtual std::string gen_field_store(const arg &a, std::vector<var_description> &vars, bool flat,
|
||||
int storer_type) const = 0;
|
||||
virtual std::string gen_type_fetch(const std::string &field_name, const tl_tree_type *tree_type,
|
||||
const std::vector<var_description> &vars, int parser_type) const = 0;
|
||||
virtual std::string gen_type_store(const std::string &field_name, const tl_tree_type *tree_type,
|
||||
const std::vector<var_description> &vars, int storer_type) const = 0;
|
||||
virtual std::string gen_var_type_fetch(const arg &a) const = 0;
|
||||
|
||||
virtual std::string gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const = 0;
|
||||
|
||||
virtual std::string gen_function_result_type(const tl_tree *result) const = 0;
|
||||
|
||||
virtual std::string gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
|
||||
const std::string &parent_class_name, int arity, int field_count,
|
||||
std::vector<var_description> &vars, int parser_type) const = 0;
|
||||
virtual std::string gen_fetch_function_end(bool has_parent, int field_count, const std::vector<var_description> &vars,
|
||||
int parser_type) const = 0;
|
||||
|
||||
virtual std::string gen_fetch_function_result_begin(const std::string &parser_name, const std::string &class_name,
|
||||
const tl_tree *result) const = 0;
|
||||
virtual std::string gen_fetch_function_result_end() const = 0;
|
||||
virtual std::string gen_fetch_function_result_any_begin(const std::string &parser_name, const std::string &class_name,
|
||||
bool is_proxy) const = 0;
|
||||
virtual std::string gen_fetch_function_result_any_end(bool is_proxy) const = 0;
|
||||
|
||||
virtual std::string gen_store_function_begin(const std::string &storer_name, const std::string &class_name, int arity,
|
||||
std::vector<var_description> &vars, int storer_type) const = 0;
|
||||
virtual std::string gen_store_function_end(const std::vector<var_description> &vars, int storer_type) const = 0;
|
||||
|
||||
virtual std::string gen_fetch_switch_begin() const = 0;
|
||||
virtual std::string gen_fetch_switch_case(const tl_combinator *t, int arity) const = 0;
|
||||
virtual std::string gen_fetch_switch_end() const = 0;
|
||||
|
||||
virtual std::string gen_constructor_begin(int field_count, const std::string &class_name, bool is_default) const = 0;
|
||||
virtual std::string gen_constructor_parameter(int field_num, const std::string &class_name, const arg &a,
|
||||
bool is_default) const = 0;
|
||||
virtual std::string gen_constructor_field_init(int field_num, const std::string &class_name, const arg &a,
|
||||
bool is_default) const = 0;
|
||||
virtual std::string gen_constructor_end(const tl_combinator *t, int field_count, bool is_default) const = 0;
|
||||
|
||||
virtual std::string gen_additional_function(const std::string &function_name, const tl_combinator *t,
|
||||
bool is_function) const;
|
||||
virtual std::string gen_additional_proxy_function_begin(const std::string &function_name, const tl_type *type,
|
||||
const std::string &class_name, int arity,
|
||||
bool is_function) const;
|
||||
virtual std::string gen_additional_proxy_function_case(const std::string &function_name, const tl_type *type,
|
||||
const std::string &class_name, int arity) const;
|
||||
virtual std::string gen_additional_proxy_function_case(const std::string &function_name, const tl_type *type,
|
||||
const tl_combinator *t, int arity, bool is_function) const;
|
||||
virtual std::string gen_additional_proxy_function_end(const std::string &function_name, const tl_type *type,
|
||||
bool is_function) const;
|
||||
};
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
||||
Reference in New Issue
Block a user