A Hugo incarnation of the blog.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

type_env.cpp 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #include "type_env.hpp"
  2. #include "type.hpp"
  3. #include "error.hpp"
  4. #include <cassert>
  5. void type_env::find_free(const type_mgr& mgr, std::set<std::string>& into) const {
  6. if(parent != nullptr) parent->find_free(mgr, into);
  7. for(auto& binding : names) {
  8. mgr.find_free(binding.second.type, into);
  9. }
  10. }
  11. void type_env::find_free_except(const type_mgr& mgr, const group& avoid,
  12. std::set<std::string>& into) const {
  13. if(parent != nullptr) parent->find_free(mgr, into);
  14. for(auto& binding : names) {
  15. if(avoid.members.find(binding.first) != avoid.members.end()) continue;
  16. mgr.find_free(binding.second.type, into);
  17. }
  18. }
  19. type_scheme_ptr type_env::lookup(const std::string& name) const {
  20. auto it = names.find(name);
  21. if(it != names.end()) return it->second.type;
  22. if(parent) return parent->lookup(name);
  23. return nullptr;
  24. }
  25. bool type_env::is_global(const std::string& name) const {
  26. auto it = names.find(name);
  27. if(it != names.end()) return it->second.vis == visibility::global;
  28. if(parent) return parent->is_global(name);
  29. return false;
  30. }
  31. void type_env::set_mangled_name(const std::string& name, const std::string& mangled) {
  32. auto it = names.find(name);
  33. // Can't set mangled name for non-existent variable.
  34. assert(it != names.end());
  35. // Local names shouldn't need mangling.
  36. assert(it->second.vis == visibility::global);
  37. it->second.mangled_name = mangled;
  38. }
  39. const std::string& type_env::get_mangled_name(const std::string& name) const {
  40. auto it = names.find(name);
  41. if(it != names.end()) {
  42. assert(it->second.mangled_name);
  43. return *it->second.mangled_name;
  44. }
  45. assert(parent != nullptr);
  46. return parent->get_mangled_name(name);
  47. }
  48. type_ptr type_env::lookup_type(const std::string& name) const {
  49. auto it = type_names.find(name);
  50. if(it != type_names.end()) return it->second;
  51. if(parent) return parent->lookup_type(name);
  52. return nullptr;
  53. }
  54. void type_env::bind(const std::string& name, type_ptr t, visibility v) {
  55. type_scheme_ptr new_scheme(new type_scheme(std::move(t)));
  56. names[name] = variable_data(std::move(new_scheme), v, std::nullopt);
  57. }
  58. void type_env::bind(const std::string& name, type_scheme_ptr t, visibility v) {
  59. names[name] = variable_data(std::move(t), v, "");
  60. }
  61. void type_env::bind_type(const std::string& type_name, type_ptr t) {
  62. if(lookup_type(type_name) != nullptr)
  63. throw type_error("redefinition of type");
  64. type_names[type_name] = t;
  65. }
  66. void type_env::generalize(const std::string& name, const group& grp, type_mgr& mgr) {
  67. auto names_it = names.find(name);
  68. assert(names_it != names.end());
  69. assert(names_it->second.type->forall.size() == 0);
  70. std::set<std::string> free_in_type;
  71. std::set<std::string> free_in_env;
  72. mgr.find_free(names_it->second.type->monotype, free_in_type);
  73. find_free_except(mgr, grp, free_in_env);
  74. for(auto& free : free_in_type) {
  75. if(free_in_env.find(free) != free_in_env.end()) continue;
  76. names_it->second.type->forall.push_back(free);
  77. }
  78. }
  79. type_env_ptr type_scope(type_env_ptr parent) {
  80. return type_env_ptr(new type_env(std::move(parent)));
  81. }