Fix typechecking of mutually recursive functions.

This commit is contained in:
Danila Fedorin 2020-06-21 00:47:26 -07:00
parent 6198738acc
commit 2d8c4d16c0
4 changed files with 15 additions and 8 deletions

View File

@ -139,7 +139,7 @@ void definition_group::typecheck(type_mgr& mgr, type_env_ptr& env) {
def_defn->typecheck(mgr); def_defn->typecheck(mgr);
} }
for(auto& def_defnn_name : group->members) { for(auto& def_defnn_name : group->members) {
this->env->generalize(def_defnn_name, mgr); this->env->generalize(def_defnn_name, *group, mgr);
} }
} }
} }

View File

@ -205,7 +205,13 @@ void type_mgr::find_free(const type_ptr& t, std::set<std::string>& into) const {
void type_mgr::find_free(const type_scheme_ptr& t, std::set<std::string>& into) const { void type_mgr::find_free(const type_scheme_ptr& t, std::set<std::string>& into) const {
std::set<std::string> monotype_free; std::set<std::string> monotype_free;
find_free(t->monotype, monotype_free); type_mgr limited_mgr;
for(auto& binding : types) {
auto existing_position = std::find(t->forall.begin(), t->forall.end(), binding.first);
if(existing_position != t->forall.end()) continue;
limited_mgr.types[binding.first] = binding.second;
}
limited_mgr.find_free(t->monotype, monotype_free);
for(auto& not_free : t->forall) { for(auto& not_free : t->forall) {
monotype_free.erase(not_free); monotype_free.erase(not_free);
} }

View File

@ -8,11 +8,11 @@ void type_env::find_free(const type_mgr& mgr, std::set<std::string>& into) const
} }
} }
void type_env::find_free_except(const type_mgr& mgr, const std::string& avoid, void type_env::find_free_except(const type_mgr& mgr, const group& avoid,
std::set<std::string>& into) const { std::set<std::string>& into) const {
if(parent != nullptr) parent->find_free(mgr, into); if(parent != nullptr) parent->find_free(mgr, into);
for(auto& binding : names) { for(auto& binding : names) {
if(binding.first == avoid) continue; if(avoid.members.find(binding.first) != avoid.members.end()) continue;
mgr.find_free(binding.second.type, into); mgr.find_free(binding.second.type, into);
} }
} }
@ -65,7 +65,7 @@ void type_env::bind_type(const std::string& type_name, type_ptr t) {
type_names[type_name] = t; type_names[type_name] = t;
} }
void type_env::generalize(const std::string& name, type_mgr& mgr) { void type_env::generalize(const std::string& name, const group& grp, type_mgr& mgr) {
auto names_it = names.find(name); auto names_it = names.find(name);
if(names_it == names.end()) throw 0; if(names_it == names.end()) throw 0;
if(names_it->second.type->forall.size() > 0) throw 0; if(names_it->second.type->forall.size() > 0) throw 0;
@ -73,7 +73,7 @@ void type_env::generalize(const std::string& name, type_mgr& mgr) {
std::set<std::string> free_in_type; std::set<std::string> free_in_type;
std::set<std::string> free_in_env; std::set<std::string> free_in_env;
mgr.find_free(names_it->second.type->monotype, free_in_type); mgr.find_free(names_it->second.type->monotype, free_in_type);
find_free_except(mgr, name, free_in_env); find_free_except(mgr, grp, free_in_env);
for(auto& free : free_in_type) { for(auto& free : free_in_type) {
if(free_in_env.find(free) != free_in_env.end()) continue; if(free_in_env.find(free) != free_in_env.end()) continue;
names_it->second.type->forall.push_back(free); names_it->second.type->forall.push_back(free);

View File

@ -2,6 +2,7 @@
#include <map> #include <map>
#include <string> #include <string>
#include <set> #include <set>
#include "graph.hpp"
#include "type.hpp" #include "type.hpp"
struct type_env; struct type_env;
@ -29,7 +30,7 @@ struct type_env {
type_env() : type_env(nullptr) {} type_env() : type_env(nullptr) {}
void find_free(const type_mgr& mgr, std::set<std::string>& into) const; void find_free(const type_mgr& mgr, std::set<std::string>& into) const;
void find_free_except(const type_mgr& mgr, const std::string& avoid, void find_free_except(const type_mgr& mgr, const group& avoid,
std::set<std::string>& into) const; std::set<std::string>& into) const;
type_scheme_ptr lookup(const std::string& name) const; type_scheme_ptr lookup(const std::string& name) const;
bool is_global(const std::string& name) const; bool is_global(const std::string& name) const;
@ -41,7 +42,7 @@ struct type_env {
void bind(const std::string& name, type_scheme_ptr t, void bind(const std::string& name, type_scheme_ptr t,
visibility v = visibility::local); visibility v = visibility::local);
void bind_type(const std::string& type_name, type_ptr t); void bind_type(const std::string& type_name, type_ptr t);
void generalize(const std::string& name, type_mgr& mgr); void generalize(const std::string& name, const group& grp, type_mgr& mgr);
}; };