/* 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 . Copyright 2017-2020 Telegram Systems LLP */ #pragma once #include #include #include "common/linalloc.hpp" namespace tlbc { using src::Lexem; using src::Lexer; using sym::sym_idx_t; extern td::LinearAllocator AR; struct Type; struct Constructor; struct TypeExpr { enum { te_Unknown, te_Type, te_Param, te_Apply, te_Add, te_GetBit, te_MulConst, te_IntConst, te_Tuple, te_Ref, te_CondType }; enum { max_const_expr = 100000, const_htable_size = 170239 }; int tp; int value; Type* type_applied; bool is_nat; // we keep integer expressions in 'TypeExpr' as well bool is_nat_subtype; // this is # or a subtype of # bool negated; // is it linearly negative bool tchk_only; // type to be used as RHS of : only int is_constexpr; // if non-zero, it is an index in `const_type_expr`, the table of all constant type expressions src::SrcLocation where; std::vector args; TypeExpr(const src::SrcLocation& loc, int _tp, int _value = 0, bool _pol = false) : tp(_tp) , value(_value) , type_applied(nullptr) , is_nat_subtype(false) , negated(_pol) , tchk_only(false) , is_constexpr(0) , where(loc) { init_is_nat(); } TypeExpr(const src::SrcLocation& loc, int _tp, int _value, std::initializer_list _arglist, bool _pol = false) : tp(_tp) , value(_value) , type_applied(nullptr) , is_nat_subtype(false) , negated(_pol) , tchk_only(false) , is_constexpr(0) , where(loc) , args(std::move(_arglist)) { init_is_nat(); } TypeExpr(const src::SrcLocation& loc, int _tp, int _value, std::vector _arglist, bool _pol = false) : tp(_tp) , value(_value) , type_applied(nullptr) , is_nat_subtype(false) , negated(_pol) , tchk_only(false) , is_constexpr(0) , where(loc) , args(std::move(_arglist)) { init_is_nat(); } void check_mode(const src::SrcLocation& loc, int mode); bool no_tchk() const; bool close(const src::SrcLocation& loc); bool bind_value(bool value_negated, Constructor& cs, bool checking_type = false); int abstract_interpret_nat() const; MinMaxSize compute_size() const; bool compute_any_bits() const; bool detect_constexpr(); int is_integer() const; bool is_anon() const; bool is_ref_to_anon() const; bool equal(const TypeExpr& other) const; void const_type_name(std::ostream& os) const; static TypeExpr* mk_intconst(const src::SrcLocation& loc, std::string int_const); static TypeExpr* mk_intconst(const src::SrcLocation& loc, unsigned int_const); static TypeExpr* mk_apply_gen(const src::SrcLocation& loc, TypeExpr* expr1, TypeExpr* expr2); static TypeExpr* mk_mulint(const src::SrcLocation& loc, TypeExpr* expr1, TypeExpr* expr2); static TypeExpr* mk_cellref(const src::SrcLocation& loc, TypeExpr* expr1); static TypeExpr* mk_apply(const src::SrcLocation& loc, int tp, TypeExpr* expr1, TypeExpr* expr2); static TypeExpr* mk_apply_empty(const src::SrcLocation& loc, sym_idx_t name, Type* type_applied); void show(std::ostream& os, const Constructor* cs = nullptr, int prio = 0, int mode = 0) const; private: void init_is_nat() { is_nat = (tp >= te_Add && tp <= te_IntConst); } unsigned long long compute_hash() const; static TypeExpr* const_htable[const_htable_size]; }; // extern TypeExpr* TypeExpr::const_htable[TypeExpr::const_htable_size]; extern TypeExpr* const_type_expr[TypeExpr::max_const_expr]; extern int const_type_expr_num; std::ostream& operator<<(std::ostream& os, const TypeExpr* te); struct Field { int field_idx; bool implicit; bool known; bool constraint; bool used; bool subrec; sym_idx_t name; TypeExpr* type; const src::SrcLocation loc; Field(const src::SrcLocation& where, bool impl, int idx, sym_idx_t fname = 0, TypeExpr* ftype = nullptr) : field_idx(idx) , implicit(impl) , known(false) , constraint(false) , used(false) , subrec(false) , name(fname) , type(ftype) , loc(where) { } void register_sym() const; std::string get_name() const; bool isomorphic_to(const Field& f, bool allow_other_names = true) const; }; struct Constructor { sym_idx_t constr_name; sym_idx_t type_name; Type* type_defined; src::SrcLocation where; unsigned long long tag; int tag_bits; int fields_num; int type_arity; bool is_fwd; bool is_enum; bool is_simple_enum; bool is_special; bool has_fixed_size; bool any_bits; MinMaxSize size; BitPfxCollection begins_with; std::vector fields; std::vector params; std::vector param_negated; std::vector param_const_val; // -1 -- not integer or not constant AdmissibilityInfo admissible_params; void set_tag(unsigned long long new_tag) { tag = new_tag; tag_bits = (tag ? 63 - td::count_trailing_zeroes_non_zero64(tag) : -1); } Constructor(const src::SrcLocation& _loc = {}, sym_idx_t cname = 0, sym_idx_t tname = 0, unsigned long long _tag = 0, Type* type = nullptr) : constr_name(cname) , type_name(tname) , type_defined(type) , where(_loc) , fields_num(0) , type_arity(0) , is_fwd(false) , is_enum(false) , is_simple_enum(false) , is_special(false) , has_fixed_size(false) , any_bits(false) { set_tag(_tag); } Field& new_field(const src::SrcLocation& where, bool implicit, sym_idx_t name); void show(std::ostream& os, int mode = 0) const; std::string get_name() const; std::string get_qualified_name() const; bool isomorphic_to(const Constructor& cs, bool allow_other_names) const; unsigned long long compute_tag() const; void check_assign_tag(); bool compute_is_fwd(); bool recompute_begins_with(); bool recompute_minmax_size(); bool recompute_any_bits(); bool compute_admissible_params(); int get_const_param(unsigned idx) const { return idx < param_const_val.size() ? param_const_val[idx] : -1; } }; std::ostream& operator<<(std::ostream& os, const Constructor& cs); struct Type { enum { _IsType = 1, _IsNat = 2, _IsPos = 4, _IsNeg = 8, _NonConst = 16 }; sym_idx_t type_name; int type_idx; int parent_type_idx; int constr_num; int arity; int used; int last_declared; static int last_declared_counter; bool produces_nat; bool is_final; bool is_builtin; bool is_enum; bool is_simple_enum; bool is_special; bool is_pfx_determ; bool is_param_determ; bool is_const_param_determ; bool is_const_param_pfx_determ; bool is_param_pfx_determ; bool is_determ; bool has_fixed_size; bool any_bits; bool is_auto; bool is_anon; bool is_unit; bool is_bool; signed char is_integer; int useful_depth; int const_param_idx; int conflict1, conflict2; MinMaxSize size; std::vector constructors; std::vector args; BitPfxCollection begins_with; AdmissibilityInfo admissible_params; std::unique_ptr cs_trie; Type(int idx, sym_idx_t _tname = 0, bool pnat = false, int _arity = -1, bool _final = false, bool _nonempty = false) : type_name(_tname) , type_idx(idx) , parent_type_idx(-1) , constr_num(0) , arity(_arity) , used(0) , last_declared(0) , produces_nat(pnat) , is_final(_final) , is_builtin(_final) , is_enum(!_final) , is_simple_enum(!_final) , is_special(false) , is_pfx_determ(false) , is_param_determ(false) , is_const_param_determ(false) , is_const_param_pfx_determ(false) , is_param_pfx_determ(false) , is_determ(false) , has_fixed_size(false) , any_bits(false) , is_auto(false) , is_anon(false) , is_unit(false) , is_bool(false) , is_integer(pnat) , useful_depth(-1) , const_param_idx(-1) , conflict1(-1) , conflict2(-1) { if (arity > 0) { args.resize(arity, 0); } if (_nonempty) { begins_with.all(); } } void bind_constructor(const src::SrcLocation& loc, Constructor* cs); bool unique_constructor_equals(const Constructor& cs, bool allow_other_names = false) const; void print_name(std::ostream& os) const; std::string get_name() const; bool recompute_begins_with(); bool recompute_minmax_size(); bool recompute_any_bits(); bool compute_admissible_params(); void compute_constructor_trie(); int detect_const_params(); bool check_conflicts(); void show_constructor_conflict(); void detect_basic_types(); bool cons_all_exact() const; int cons_common_len() const; bool is_const_arg(int p) const; std::vector get_all_param_values(int p) const; std::vector get_constr_by_param_value(int p, int pv) const; void renew_last_declared() { last_declared = ++last_declared_counter; } }; extern TypeExpr type_Type; struct SymVal : sym::SymValBase { TypeExpr* sym_type; SymVal(int _type, int _idx, TypeExpr* _stype = nullptr) : sym::SymValBase(_type, _idx), sym_type(_stype) { } TypeExpr* get_type() const { return sym_type; } }; struct SymValType : SymVal { Type* type_ref; explicit SymValType(Type* _type = nullptr) : SymVal(sym::SymValBase::_Typename, 0, &type_Type), type_ref(_type) { } }; extern sym_idx_t Nat_name, Eq_name, Less_name, Leq_name; extern Type *Nat_type, *Eq_type; extern Type *NatWidth_type, *NatLess_type, *NatLeq_type, *Int_type, *UInt_type; extern int types_num, builtin_types_num; extern std::vector types; } // namespace tlbc