// // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020 // // 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 #include 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(c - 'A' + 'a') : c; } char TL_writer::to_upper(char c) { return 'a' <= c && c <= 'z' ? static_cast(c - 'a' + 'A') : c; } std::vector TL_writer::get_additional_functions() const { return std::vector(); } 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(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 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(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 result of two function calls is 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(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(a.type))) { return false; } } else { assert(arg_type == NODE_TYPE_ARRAY); const tl_tree_array *arr = static_cast(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(b.type))) { return false; } } } } tl_tree *result = constructor->result; if (result->get_type() == NODE_TYPE_TYPE) { if (!is_type_supported(static_cast(result))) { return false; } } else { assert(result->get_type() == NODE_TYPE_VAR_TYPE); const tl_tree_var_type *t = static_cast(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 is_function) 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(a.type); assert(arg_type->children.size() == static_cast(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(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