#pragma once #include #include #include #include #include struct type_mgr; struct type { virtual ~type() = default; virtual void print(const type_mgr& mgr, std::ostream& to) const = 0; }; using type_ptr = std::shared_ptr; struct type_scheme { std::vector forall; type_ptr monotype; type_scheme(type_ptr type) : forall(), monotype(std::move(type)) {} void print(const type_mgr& mgr, std::ostream& to) const; type_ptr instantiate(type_mgr& mgr) const; }; using type_scheme_ptr = std::shared_ptr; struct type_var : public type { std::string name; type_var(std::string n) : name(std::move(n)) {} void print(const type_mgr& mgr, std::ostream& to) const; }; struct type_base : public type { std::string name; type_base(std::string n) : name(std::move(n)) {} void print(const type_mgr& mgr, std::ostream& to) const; }; struct type_data : public type_base { struct constructor { int tag; }; std::map constructors; type_data(std::string n) : type_base(std::move(n)) {} }; struct type_arr : public type { type_ptr left; type_ptr right; type_arr(type_ptr l, type_ptr r) : left(std::move(l)), right(std::move(r)) {} void print(const type_mgr& mgr, std::ostream& to) const; }; struct type_mgr { int last_id = 0; std::map types; std::string new_type_name(); type_ptr new_type(); type_ptr new_arrow_type(); void unify(type_ptr l, type_ptr r); type_ptr resolve(type_ptr t, type_var*& var) const; void bind(const std::string& s, type_ptr t); void find_free(const type_ptr& t, std::set& into) const; };