#include "type_env.hpp" #include "type.hpp" #include "error.hpp" void type_env::find_free(const type_mgr& mgr, std::set& into) const { if(parent != nullptr) parent->find_free(mgr, into); for(auto& binding : names) { mgr.find_free(binding.second.type, into); } } void type_env::find_free_except(const type_mgr& mgr, const group& avoid, std::set& into) const { if(parent != nullptr) parent->find_free(mgr, into); for(auto& binding : names) { if(avoid.members.find(binding.first) != avoid.members.end()) continue; mgr.find_free(binding.second.type, into); } } type_scheme_ptr type_env::lookup(const std::string& name) const { auto it = names.find(name); if(it != names.end()) return it->second.type; if(parent) return parent->lookup(name); return nullptr; } bool type_env::is_global(const std::string& name) const { auto it = names.find(name); if(it != names.end()) return it->second.vis == visibility::global; if(parent) return parent->is_global(name); return false; } void type_env::set_mangled_name(const std::string& name, const std::string& mangled) { auto it = names.find(name); if(it != names.end()) it->second.mangled_name = mangled; } const std::string& type_env::get_mangled_name(const std::string& name) const { auto it = names.find(name); if(it != names.end()) return (it->second.mangled_name != "") ? it->second.mangled_name : name; if(parent) return parent->get_mangled_name(name); return name; } type_ptr type_env::lookup_type(const std::string& name) const { auto it = type_names.find(name); if(it != type_names.end()) return it->second; if(parent) return parent->lookup_type(name); return nullptr; } void type_env::bind(const std::string& name, type_ptr t, visibility v) { type_scheme_ptr new_scheme(new type_scheme(std::move(t))); names[name] = variable_data(std::move(new_scheme), v, ""); } void type_env::bind(const std::string& name, type_scheme_ptr t, visibility v) { names[name] = variable_data(std::move(t), v, ""); } void type_env::bind_type(const std::string& type_name, type_ptr t) { if(lookup_type(type_name) != nullptr) throw type_error("redefinition of type"); type_names[type_name] = t; } void type_env::generalize(const std::string& name, const group& grp, type_mgr& mgr) { auto names_it = names.find(name); assert(names_it != names.end()); assert(names_it->second.type->forall.size() == 0); std::set free_in_type; std::set free_in_env; mgr.find_free(names_it->second.type->monotype, free_in_type); find_free_except(mgr, grp, free_in_env); for(auto& free : free_in_type) { if(free_in_env.find(free) != free_in_env.end()) continue; names_it->second.type->forall.push_back(free); } } type_env_ptr type_scope(type_env_ptr parent) { return type_env_ptr(new type_env(std::move(parent))); }