mirror of
				https://github.com/ton-blockchain/ton
				synced 2025-03-09 15:40:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			290 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			290 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|     This file is part of TON Blockchain Library.
 | |
| 
 | |
|     TON Blockchain Library is free software: you can redistribute it and/or modify
 | |
|     it under the terms of the GNU Lesser General Public License as published by
 | |
|     the Free Software Foundation, either version 2 of the License, or
 | |
|     (at your option) any later version.
 | |
| 
 | |
|     TON Blockchain Library is distributed in the hope that it will be useful,
 | |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|     GNU Lesser General Public License for more details.
 | |
| 
 | |
|     You should have received a copy of the GNU Lesser General Public License
 | |
|     along with TON Blockchain Library.  If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
|     Copyright 2017-2020 Telegram Systems LLP
 | |
| */
 | |
| #pragma once
 | |
| 
 | |
| namespace tlbc {
 | |
| 
 | |
| extern std::set<std::string> forbidden_cpp_idents, local_forbidden_cpp_idents;
 | |
| 
 | |
| struct CppIdentSet {
 | |
|   std::set<std::string> cpp_idents;
 | |
|   const std::set<std::string>* extra_forbidden_idents;
 | |
|   CppIdentSet(const std::set<std::string>* forbid = nullptr) : extra_forbidden_idents(forbid) {
 | |
|   }
 | |
|   static std::string compute_cpp_ident(std::string orig_ident, int count = 0);
 | |
|   std::string new_ident(std::string orig_ident, int count = 0, std::string suffix = "");
 | |
|   bool insert(std::string ident) {
 | |
|     return cpp_idents.insert(ident).second;
 | |
|   }
 | |
|   bool defined(std::string ident) {
 | |
|     return cpp_idents.count(ident);
 | |
|   }
 | |
|   bool is_good_ident(std::string ident);
 | |
|   void clear() {
 | |
|     cpp_idents.clear();
 | |
|   }
 | |
| };
 | |
| 
 | |
| extern CppIdentSet global_cpp_ids;
 | |
| 
 | |
| struct Action {
 | |
|   int fixed_size;
 | |
|   bool is_pure;
 | |
|   bool is_constraint;
 | |
|   std::string action;
 | |
|   Action(int _size) : fixed_size(_size), is_pure(false), is_constraint(false) {
 | |
|   }
 | |
|   Action(std::string _action, bool _cst = false)
 | |
|       : fixed_size(-1), is_pure(false), is_constraint(_cst), action(_action) {
 | |
|   }
 | |
|   Action(const std::ostringstream& ss, bool _cst = false)
 | |
|       : fixed_size(-1), is_pure(false), is_constraint(_cst), action(ss.str()) {
 | |
|   }
 | |
|   Action(std::ostringstream&& ss, bool _cst = false)
 | |
|       : fixed_size(-1), is_pure(false), is_constraint(_cst), action(std::move(ss).str()) {
 | |
|   }
 | |
|   void show(std::ostream& os) const;
 | |
|   bool may_combine(const Action& next) const;
 | |
|   bool operator+=(const Action& next);
 | |
| };
 | |
| 
 | |
| enum cpp_val_type {
 | |
|   ct_unknown,
 | |
|   ct_void = 1,
 | |
|   ct_slice = 2,
 | |
|   ct_cell = 3,
 | |
|   ct_typeref = 4,
 | |
|   ct_typeptr = 5,
 | |
|   ct_bits = 6,
 | |
|   ct_bitstring = 7,
 | |
|   ct_integer = 8,
 | |
|   ct_bool = 10,
 | |
|   ct_enum = 11,
 | |
|   ct_int32 = 12,
 | |
|   ct_uint32 = 13,
 | |
|   ct_int64 = 14,
 | |
|   ct_uint64 = 15,
 | |
|   ct_subrecord = 16
 | |
| };
 | |
| 
 | |
| struct CppValType {
 | |
|   cpp_val_type vt;
 | |
|   int size;
 | |
|   CppValType(cpp_val_type _vt = ct_unknown, int _size = -1) : vt(_vt), size(_size) {
 | |
|   }
 | |
|   cpp_val_type get() const {
 | |
|     return vt;
 | |
|   }
 | |
|   void show(std::ostream& os, bool pass_value = false) const;
 | |
|   bool needs_move() const;
 | |
| };
 | |
| 
 | |
| extern std::ostream& operator<<(std::ostream& os, CppValType cvt);
 | |
| 
 | |
| class CppTypeCode {
 | |
|   Type& type;
 | |
|   bool ok;
 | |
|   bool builtin;
 | |
|   bool inline_get_tag;
 | |
|   bool inline_skip;
 | |
|   bool inline_validate_skip;
 | |
|   bool simple_get_size;
 | |
|   bool simple_cons_tags;
 | |
|   bool incremental_cons_tags;
 | |
| 
 | |
|  public:
 | |
|   int params;
 | |
|   int tot_params;
 | |
|   int ret_params;
 | |
|   int cons_num;
 | |
|   int common_cons_len;
 | |
|   std::vector<std::string> cons_enum_name;
 | |
|   std::vector<int> cons_enum_value;
 | |
|   std::vector<int> cons_tag_map;
 | |
|   std::vector<bool> cons_tag_exact;
 | |
|   std::vector<int> cons_idx_by_enum;
 | |
|   std::string cpp_type_var_name;
 | |
|   std::string cpp_type_class_name;
 | |
|   std::string cpp_type_template_name;
 | |
| 
 | |
|   struct ConsRecord;
 | |
| 
 | |
|   struct ConsField {
 | |
|     const Field& field;
 | |
|     const ConsRecord* subrec;
 | |
|     std::string name;
 | |
|     cpp_val_type ctype;
 | |
|     int size;
 | |
|     int orig_idx;
 | |
|     bool implicit;
 | |
|     ConsField(const Field& _field, std::string _name, cpp_val_type _ctype, int _size, int _idx,
 | |
|               const ConsRecord* _subrec = nullptr, bool _implicit = false)
 | |
|         : field(_field), subrec(_subrec), name(_name), ctype(_ctype), size(_size), orig_idx(_idx), implicit(_implicit) {
 | |
|       assert(ctype != ct_subrecord || subrec);
 | |
|     }
 | |
|     CppValType get_cvt() const {
 | |
|       return {ctype, size};
 | |
|     }
 | |
|     void print_type(std::ostream& os, bool pass_value = false) const;
 | |
|   };
 | |
| 
 | |
|   struct ConsRecord {
 | |
|     const CppTypeCode& cpp_type;
 | |
|     const Constructor& constr;
 | |
|     int cons_idx;
 | |
|     bool is_trivial;
 | |
|     bool is_small;
 | |
|     bool triv_conflict;
 | |
|     bool has_trivial_name;
 | |
|     bool inline_record;
 | |
|     bool declared;
 | |
|     cpp_val_type equiv_cpp_type;
 | |
|     std::vector<cpp_val_type> equiv_cpp_types;
 | |
|     std::string cpp_name;
 | |
|     std::vector<ConsField> cpp_fields;
 | |
|     ConsRecord(const CppTypeCode& _cpp_type, const Constructor& _constr, int idx, bool _triv = false)
 | |
|         : cpp_type(_cpp_type), constr(_constr), cons_idx(idx), is_trivial(_triv), declared(false) {
 | |
|     }
 | |
|     bool recover_idents(CppIdentSet& idents) const;
 | |
|     void declare_record(std::ostream& os, std::string nl, int options);
 | |
|     bool declare_record_unpack(std::ostream& os, std::string nl, int options);
 | |
|     bool declare_record_pack(std::ostream& os, std::string nl, int options);
 | |
|     void print_full_name(std::ostream& os) const;
 | |
|   };
 | |
|   std::vector<ConsRecord> records;
 | |
| 
 | |
|  private:
 | |
|   std::vector<std::string> type_param_name;
 | |
|   std::vector<bool> type_param_is_nat;
 | |
|   std::vector<bool> type_param_is_neg;
 | |
|   std::string template_args;
 | |
|   std::string constructor_args;
 | |
|   std::string skip_extra_args;
 | |
|   std::string skip_extra_args_pass;
 | |
|   CppIdentSet local_cpp_ids;
 | |
|   bool init();
 | |
| 
 | |
|  public:
 | |
|   CppTypeCode(Type& _type) : type(_type), local_cpp_ids(&local_forbidden_cpp_idents) {
 | |
|     ok = init();
 | |
|   }
 | |
|   bool is_ok() const {
 | |
|     return ok;
 | |
|   }
 | |
|   void generate(std::ostream& os, int options = 0);
 | |
| 
 | |
|  private:
 | |
|   bool compute_simple_cons_tags();
 | |
|   bool check_incremental_cons_tags() const;
 | |
|   unsigned long long compute_selector_mask() const;
 | |
|   void assign_class_name();
 | |
|   void assign_cons_names();
 | |
|   void assign_class_field_names();
 | |
|   void assign_cons_values();
 | |
|   void assign_record_cons_names();
 | |
|   void generate_cons_enum(std::ostream& os);
 | |
|   void generate_type_constructor(std::ostream& os, int options);
 | |
|   void generate_type_fields(std::ostream& os, int options);
 | |
|   void generate_header(std::ostream& os, int options = 0);
 | |
|   void generate_body(std::ostream& os, int options = 0);
 | |
|   void generate_cons_len_array(std::ostream& os, std::string nl, int options = 0);
 | |
|   void generate_cons_tag_array(std::ostream& os, std::string nl, int options = 0);
 | |
|   void generate_cons_tag_info(std::ostream& os, std::string nl, int options = 0);
 | |
|   void generate_skip_method(std::ostream& os, int options = 0);
 | |
|   void generate_skip_cons_method(std::ostream& os, std::string nl, int cidx, int options);
 | |
|   void generate_cons_tag_check(std::ostream& os, std::string nl, int cidx, bool force = false);
 | |
|   void generate_check_tag_method(std::ostream& os);
 | |
|   void generate_unpack_method(std::ostream& os, ConsRecord& rec, int options);
 | |
|   void generate_pack_method(std::ostream& os, ConsRecord& rec, int options);
 | |
|   void generate_ext_fetch_to(std::ostream& os, int options);
 | |
|   void generate_fetch_enum_method(std::ostream& os, int options);
 | |
|   void generate_store_enum_method(std::ostream& os, int options);
 | |
|   void generate_print_type_body(std::ostream& os, std::string nl);
 | |
|   void generate_print_method(std::ostream& os, int options = 0);
 | |
|   void generate_print_cons_method(std::ostream& os, std::string nl, int cidx, int options);
 | |
|   void generate_get_tag_body(std::ostream& os, std::string nl);
 | |
|   void generate_get_tag_subcase(std::ostream& os, std::string nl, const BinTrie* trie, int depth) const;
 | |
|   void generate_get_tag_param(std::ostream& os, std::string nl, unsigned long long tag,
 | |
|                               unsigned long long params = std::numeric_limits<td::uint64>::max()) const;
 | |
|   void generate_get_tag_param1(std::ostream& os, std::string nl, const char A[4],
 | |
|                                const std::string param_names[1]) const;
 | |
|   void generate_get_tag_param2(std::ostream& os, std::string nl, const char A[4][4],
 | |
|                                const std::string param_names[2]) const;
 | |
|   void generate_get_tag_param3(std::ostream& os, std::string nl, const char A[4][4][4],
 | |
|                                const std::string param_names[3]) const;
 | |
|   bool match_param_pattern(std::ostream& os, std::string nl, const char A[4], int mask, std::string pattern,
 | |
|                            std::string param_name) const;
 | |
|   std::string get_nat_param_name(int idx) const;
 | |
|   void generate_tag_pfx_selector(std::ostream& os, std::string nl, const BinTrie& trie, int d, int min_size) const;
 | |
|   bool generate_get_tag_pfx_distinguisher(std::ostream& os, std::string nl, const std::vector<int>& constr_list,
 | |
|                                           bool in_block) const;
 | |
| 
 | |
|  private:
 | |
|   std::vector<Action> actions;
 | |
|   int incomplete;
 | |
|   int tmp_ints;
 | |
|   bool needs_tmp_cell;
 | |
|   std::vector<std::string> tmp_vars;
 | |
|   std::vector<std::string> field_vars;
 | |
|   std::vector<bool> field_var_set;
 | |
|   std::vector<bool> param_var_set;
 | |
|   std::vector<bool> param_constraint_used;
 | |
|   std::vector<std::pair<std::string, const TypeExpr*>> postponed_equate;
 | |
|   CppIdentSet tmp_cpp_ids;
 | |
|   void clear_context();
 | |
|   void init_cons_context(const Constructor& constr);
 | |
|   std::string new_tmp_var(std::string hint);
 | |
|   std::string new_tmp_var();
 | |
|   void add_action(const Action& act);
 | |
|   void output_actions(std::ostream& os, std::string nl, int options);
 | |
|   void output_cpp_expr(std::ostream& os, const TypeExpr* expr, int prio = 0, bool allow_type_neg = false) const;
 | |
|   void output_cpp_sizeof_expr(std::ostream& os, const TypeExpr* expr, int prio) const;
 | |
|   void output_negative_type_arguments(std::ostream& os, const TypeExpr* expr);
 | |
|   bool can_compute(const TypeExpr* expr) const;
 | |
|   bool can_use_to_compute(const TypeExpr* expr, int i) const;
 | |
|   bool can_compute_sizeof(const TypeExpr* expr) const;
 | |
|   bool is_self(const TypeExpr* expr, const Constructor& constr) const;
 | |
|   void add_compute_actions(const TypeExpr* expr, int i, std::string bind_to);
 | |
|   void identify_cons_params(const Constructor& constr, int options);
 | |
|   void identify_cons_neg_params(const Constructor& constr, int options);
 | |
|   void bind_record_fields(const ConsRecord& rec, int options);
 | |
|   void add_cons_tag_check(const Constructor& constr, int cidx, int options);
 | |
|   void add_cons_tag_store(const Constructor& constr, int cidx);
 | |
|   std::string add_fetch_nat_field(const Constructor& constr, const Field& field, int options);
 | |
|   void add_store_nat_field(const Constructor& constr, const Field& field, int options);
 | |
|   void add_remaining_param_constraints_check(const Constructor& constr, int options);
 | |
|   void compute_implicit_field(const Constructor& constr, const Field& field, int options);
 | |
|   bool add_constraint_check(const Constructor& constr, const Field& field, int options);
 | |
|   void add_postponed_equate_actions();
 | |
|   void output_fetch_field(std::ostream& os, std::string field_name, const TypeExpr* expr, cpp_val_type cvt);
 | |
|   void output_fetch_subrecord(std::ostream& os, std::string field_name, const ConsRecord* subrec);
 | |
|   void output_store_field(std::ostream& os, std::string field_name, const TypeExpr* expr, cpp_val_type cvt);
 | |
|   void add_store_subrecord(std::string field_name, const ConsRecord* subrec);
 | |
|   void generate_skip_field(const Constructor& constr, const Field& field, int options);
 | |
|   void generate_print_field(const Constructor& constr, const Field& field, int options);
 | |
|   bool output_print_simple_field(std::ostream& os, const Field& field, std::string field_name, const TypeExpr* expr);
 | |
|   void generate_unpack_field(const ConsField& fi, const Constructor& constr, const Field& field, int options);
 | |
|   void generate_pack_field(const ConsField& fi, const Constructor& constr, const Field& field, int options);
 | |
| };
 | |
| 
 | |
| extern std::vector<std::unique_ptr<CppTypeCode>> cpp_type;
 | |
| 
 | |
| extern bool add_type_members;
 | |
| 
 | |
| }  // namespace tlbc
 |