2020-05-25 21:20:41 -07:00
|
|
|
#include "type_env.hpp"
|
|
|
|
#include "type.hpp"
|
|
|
|
|
2020-05-30 16:40:27 -07:00
|
|
|
void type_env::find_free(const type_mgr& mgr, std::set<std::string>& into) const {
|
|
|
|
if(parent != nullptr) parent->find_free(mgr, into);
|
|
|
|
for(auto& binding : names) {
|
2020-05-31 00:34:12 -07:00
|
|
|
mgr.find_free(binding.second.type, into);
|
2020-05-30 16:40:27 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void type_env::find_free_except(const type_mgr& mgr, const std::string& avoid,
|
|
|
|
std::set<std::string>& into) const {
|
|
|
|
if(parent != nullptr) parent->find_free(mgr, into);
|
|
|
|
for(auto& binding : names) {
|
|
|
|
if(binding.first == avoid) continue;
|
2020-05-31 00:34:12 -07:00
|
|
|
mgr.find_free(binding.second.type, into);
|
2020-05-30 16:40:27 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-25 21:20:41 -07:00
|
|
|
type_scheme_ptr type_env::lookup(const std::string& name) const {
|
|
|
|
auto it = names.find(name);
|
2020-05-31 00:34:12 -07:00
|
|
|
if(it != names.end()) return it->second.type;
|
2020-05-25 21:20:41 -07:00
|
|
|
if(parent) return parent->lookup(name);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-05-31 18:52:52 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-06-01 00:23:41 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-05-25 21:20:41 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-05-31 00:34:12 -07:00
|
|
|
void type_env::bind(const std::string& name, type_ptr t, visibility v) {
|
|
|
|
type_scheme_ptr new_scheme(new type_scheme(std::move(t)));
|
2020-06-01 00:23:41 -07:00
|
|
|
names[name] = variable_data(std::move(new_scheme), v, "");
|
2020-05-25 21:20:41 -07:00
|
|
|
}
|
|
|
|
|
2020-05-31 00:34:12 -07:00
|
|
|
void type_env::bind(const std::string& name, type_scheme_ptr t, visibility v) {
|
2020-06-01 00:23:41 -07:00
|
|
|
names[name] = variable_data(std::move(t), v, "");
|
2020-05-25 21:20:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void type_env::bind_type(const std::string& type_name, type_ptr t) {
|
|
|
|
if(lookup_type(type_name) != nullptr) throw 0;
|
|
|
|
type_names[type_name] = t;
|
|
|
|
}
|
|
|
|
|
|
|
|
void type_env::generalize(const std::string& name, type_mgr& mgr) {
|
|
|
|
auto names_it = names.find(name);
|
|
|
|
if(names_it == names.end()) throw 0;
|
2020-05-31 00:34:12 -07:00
|
|
|
if(names_it->second.type->forall.size() > 0) throw 0;
|
2020-05-25 21:20:41 -07:00
|
|
|
|
2020-05-30 16:40:27 -07:00
|
|
|
std::set<std::string> free_in_type;
|
|
|
|
std::set<std::string> free_in_env;
|
2020-05-31 00:34:12 -07:00
|
|
|
mgr.find_free(names_it->second.type->monotype, free_in_type);
|
2020-05-30 16:40:27 -07:00
|
|
|
find_free_except(mgr, name, free_in_env);
|
|
|
|
for(auto& free : free_in_type) {
|
|
|
|
if(free_in_env.find(free) != free_in_env.end()) continue;
|
2020-05-31 00:34:12 -07:00
|
|
|
names_it->second.type->forall.push_back(free);
|
2020-05-25 21:20:41 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type_env_ptr type_scope(type_env_ptr parent) {
|
|
|
|
return type_env_ptr(new type_env(std::move(parent)));
|
|
|
|
}
|