Compare commits
3 Commits
4586bd0188
...
7f8dae74ac
Author | SHA1 | Date | |
---|---|---|---|
7f8dae74ac | |||
08503116ff | |||
a1d679a59d |
|
@ -26,8 +26,8 @@ void definition_defn::find_free(type_mgr& mgr, type_env_ptr& env) {
|
||||||
body->find_free(mgr, var_env, free_variables);
|
body->find_free(mgr, var_env, free_variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
void definition_defn::insert_types(type_mgr& mgr) {
|
void definition_defn::insert_types(type_mgr& mgr, visibility v) {
|
||||||
env->bind(name, full_type);
|
env->bind(name, full_type, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void definition_defn::typecheck(type_mgr& mgr) {
|
void definition_defn::typecheck(type_mgr& mgr) {
|
||||||
|
@ -114,15 +114,13 @@ void definition_group::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std:
|
||||||
|
|
||||||
for(auto& def_pair : defs_defn) {
|
for(auto& def_pair : defs_defn) {
|
||||||
def_pair.second->find_free(mgr, env);
|
def_pair.second->find_free(mgr, env);
|
||||||
std::set<std::string> local_dependencies;
|
|
||||||
for(auto& free_var : def_pair.second->free_variables) {
|
for(auto& free_var : def_pair.second->free_variables) {
|
||||||
if(defs_defn.find(free_var) == defs_defn.end()) {
|
if(defs_defn.find(free_var) == defs_defn.end()) {
|
||||||
into.insert(free_var);
|
into.insert(free_var);
|
||||||
} else {
|
} else {
|
||||||
local_dependencies.insert(free_var);
|
def_pair.second->nearby_variables.insert(free_var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::swap(def_pair.second->free_variables, local_dependencies);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +138,7 @@ void definition_group::typecheck(type_mgr& mgr) {
|
||||||
def_defn.second->find_free(mgr, env);
|
def_defn.second->find_free(mgr, env);
|
||||||
dependency_graph.add_function(def_defn.second->name);
|
dependency_graph.add_function(def_defn.second->name);
|
||||||
|
|
||||||
for(auto& dependency : def_defn.second->free_variables) {
|
for(auto& dependency : def_defn.second->nearby_variables) {
|
||||||
if(defs_defn.find(dependency) == defs_defn.end())
|
if(defs_defn.find(dependency) == defs_defn.end())
|
||||||
throw 0;
|
throw 0;
|
||||||
dependency_graph.add_edge(def_defn.second->name, dependency);
|
dependency_graph.add_edge(def_defn.second->name, dependency);
|
||||||
|
@ -152,7 +150,7 @@ void definition_group::typecheck(type_mgr& mgr) {
|
||||||
auto& group = *it;
|
auto& group = *it;
|
||||||
for(auto& def_defnn_name : group->members) {
|
for(auto& def_defnn_name : group->members) {
|
||||||
auto& def_defn = defs_defn.find(def_defnn_name)->second;
|
auto& def_defn = defs_defn.find(def_defnn_name)->second;
|
||||||
def_defn->insert_types(mgr);
|
def_defn->insert_types(mgr, vis);
|
||||||
}
|
}
|
||||||
for(auto& def_defnn_name : group->members) {
|
for(auto& def_defnn_name : group->members) {
|
||||||
auto& def_defn = defs_defn.find(def_defnn_name)->second;
|
auto& def_defn = defs_defn.find(def_defnn_name)->second;
|
||||||
|
|
|
@ -30,6 +30,7 @@ struct definition_defn {
|
||||||
type_env_ptr env;
|
type_env_ptr env;
|
||||||
type_env_ptr var_env;
|
type_env_ptr var_env;
|
||||||
std::set<std::string> free_variables;
|
std::set<std::string> free_variables;
|
||||||
|
std::set<std::string> nearby_variables;
|
||||||
type_ptr full_type;
|
type_ptr full_type;
|
||||||
type_ptr return_type;
|
type_ptr return_type;
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@ struct definition_defn {
|
||||||
}
|
}
|
||||||
|
|
||||||
void find_free(type_mgr& mgr, type_env_ptr& env);
|
void find_free(type_mgr& mgr, type_env_ptr& env);
|
||||||
void insert_types(type_mgr& mgr);
|
void insert_types(type_mgr& mgr, visibility v);
|
||||||
void typecheck(type_mgr& mgr);
|
void typecheck(type_mgr& mgr);
|
||||||
void compile();
|
void compile();
|
||||||
void declare_llvm(llvm_context& ctx);
|
void declare_llvm(llvm_context& ctx);
|
||||||
|
@ -75,9 +76,11 @@ using definition_data_ptr = std::unique_ptr<definition_data>;
|
||||||
struct definition_group {
|
struct definition_group {
|
||||||
std::map<std::string, definition_data_ptr> defs_data;
|
std::map<std::string, definition_data_ptr> defs_data;
|
||||||
std::map<std::string, definition_defn_ptr> defs_defn;
|
std::map<std::string, definition_defn_ptr> defs_defn;
|
||||||
|
visibility vis;
|
||||||
type_env_ptr env;
|
type_env_ptr env;
|
||||||
|
|
||||||
|
definition_group(visibility v = visibility::local) : vis(v) {}
|
||||||
|
|
||||||
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
|
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
|
||||||
void typecheck(type_mgr& mgr);
|
void typecheck(type_mgr& mgr);
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,10 +33,10 @@ void typecheck_program(
|
||||||
type_ptr binop_type = type_ptr(new type_arr(
|
type_ptr binop_type = type_ptr(new type_arr(
|
||||||
int_type_app,
|
int_type_app,
|
||||||
type_ptr(new type_arr(int_type_app, int_type_app))));
|
type_ptr(new type_arr(int_type_app, int_type_app))));
|
||||||
env->bind("+", binop_type);
|
env->bind("+", binop_type, visibility::global);
|
||||||
env->bind("-", binop_type);
|
env->bind("-", binop_type, visibility::global);
|
||||||
env->bind("*", binop_type);
|
env->bind("*", binop_type, visibility::global);
|
||||||
env->bind("/", binop_type);
|
env->bind("/", binop_type, visibility::global);
|
||||||
|
|
||||||
std::set<std::string> free;
|
std::set<std::string> free;
|
||||||
defs.find_free(mgr, env, free);
|
defs.find_free(mgr, env, free);
|
||||||
|
@ -44,7 +44,7 @@ void typecheck_program(
|
||||||
|
|
||||||
for(auto& pair : defs.env->names) {
|
for(auto& pair : defs.env->names) {
|
||||||
std::cout << pair.first << ": ";
|
std::cout << pair.first << ": ";
|
||||||
pair.second->print(mgr, std::cout);
|
pair.second.type->print(mgr, std::cout);
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "parser.hpp"
|
#include "parser.hpp"
|
||||||
#include "parsed_type.hpp"
|
#include "parsed_type.hpp"
|
||||||
|
|
||||||
definition_group global_defs;
|
definition_group global_defs(visibility::global);
|
||||||
|
|
||||||
extern yy::parser::symbol_type yylex();
|
extern yy::parser::symbol_type yylex();
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "error.hpp"
|
#include "error.hpp"
|
||||||
|
|
||||||
|
bool type::is_arrow(const type_mgr& mgr) const { return false; }
|
||||||
|
|
||||||
void type_scheme::print(const type_mgr& mgr, std::ostream& to) const {
|
void type_scheme::print(const type_mgr& mgr, std::ostream& to) const {
|
||||||
if(forall.size() != 0) {
|
if(forall.size() != 0) {
|
||||||
to << "forall ";
|
to << "forall ";
|
||||||
|
@ -34,20 +36,35 @@ void type_var::print(const type_mgr& mgr, std::ostream& to) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool type_var::is_arrow(const type_mgr& mgr) const {
|
||||||
|
auto it = mgr.types.find(name);
|
||||||
|
if(it != mgr.types.end()) {
|
||||||
|
return it->second->is_arrow(mgr);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void type_base::print(const type_mgr& mgr, std::ostream& to) const {
|
void type_base::print(const type_mgr& mgr, std::ostream& to) const {
|
||||||
to << name;
|
to << name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void type_arr::print(const type_mgr& mgr, std::ostream& to) const {
|
void type_arr::print(const type_mgr& mgr, std::ostream& to) const {
|
||||||
|
bool print_parenths = left->is_arrow(mgr);
|
||||||
|
if(print_parenths) to << "(";
|
||||||
left->print(mgr, to);
|
left->print(mgr, to);
|
||||||
to << " -> (";
|
if(print_parenths) to << ")";
|
||||||
|
to << " -> ";
|
||||||
right->print(mgr, to);
|
right->print(mgr, to);
|
||||||
to << ")";
|
}
|
||||||
|
|
||||||
|
bool type_arr::is_arrow(const type_mgr& mgr) const {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void type_app::print(const type_mgr& mgr, std::ostream& to) const {
|
void type_app::print(const type_mgr& mgr, std::ostream& to) const {
|
||||||
constructor->print(mgr, to);
|
constructor->print(mgr, to);
|
||||||
to << "* ";
|
to << "*";
|
||||||
for(auto& arg : arguments) {
|
for(auto& arg : arguments) {
|
||||||
to << " ";
|
to << " ";
|
||||||
arg->print(mgr, to);
|
arg->print(mgr, to);
|
||||||
|
|
|
@ -11,6 +11,7 @@ struct type {
|
||||||
virtual ~type() = default;
|
virtual ~type() = default;
|
||||||
|
|
||||||
virtual void print(const type_mgr& mgr, std::ostream& to) const = 0;
|
virtual void print(const type_mgr& mgr, std::ostream& to) const = 0;
|
||||||
|
virtual bool is_arrow(const type_mgr& mgr) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
using type_ptr = std::shared_ptr<type>;
|
using type_ptr = std::shared_ptr<type>;
|
||||||
|
@ -34,6 +35,7 @@ struct type_var : public type {
|
||||||
: name(std::move(n)) {}
|
: name(std::move(n)) {}
|
||||||
|
|
||||||
void print(const type_mgr& mgr, std::ostream& to) const;
|
void print(const type_mgr& mgr, std::ostream& to) const;
|
||||||
|
bool is_arrow(const type_mgr& mgr) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct type_base : public type {
|
struct type_base : public type {
|
||||||
|
@ -65,6 +67,7 @@ struct type_arr : public type {
|
||||||
: left(std::move(l)), right(std::move(r)) {}
|
: left(std::move(l)), right(std::move(r)) {}
|
||||||
|
|
||||||
void print(const type_mgr& mgr, std::ostream& to) const;
|
void print(const type_mgr& mgr, std::ostream& to) const;
|
||||||
|
bool is_arrow(const type_mgr& mgr) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct type_app : public type {
|
struct type_app : public type {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
void type_env::find_free(const type_mgr& mgr, std::set<std::string>& into) const {
|
void type_env::find_free(const type_mgr& mgr, 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) {
|
||||||
mgr.find_free(binding.second, into);
|
mgr.find_free(binding.second.type, into);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,13 +13,13 @@ void type_env::find_free_except(const type_mgr& mgr, const std::string& avoid,
|
||||||
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(binding.first == avoid) continue;
|
||||||
mgr.find_free(binding.second, into);
|
mgr.find_free(binding.second.type, into);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type_scheme_ptr type_env::lookup(const std::string& name) const {
|
type_scheme_ptr type_env::lookup(const std::string& name) const {
|
||||||
auto it = names.find(name);
|
auto it = names.find(name);
|
||||||
if(it != names.end()) return it->second;
|
if(it != names.end()) return it->second.type;
|
||||||
if(parent) return parent->lookup(name);
|
if(parent) return parent->lookup(name);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -31,12 +31,13 @@ type_ptr type_env::lookup_type(const std::string& name) const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void type_env::bind(const std::string& name, type_ptr t) {
|
void type_env::bind(const std::string& name, type_ptr t, visibility v) {
|
||||||
names[name] = type_scheme_ptr(new type_scheme(t));
|
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) {
|
void type_env::bind(const std::string& name, type_scheme_ptr t, visibility v) {
|
||||||
names[name] = t;
|
names[name] = variable_data(std::move(t), v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void type_env::bind_type(const std::string& type_name, type_ptr t) {
|
void type_env::bind_type(const std::string& type_name, type_ptr t) {
|
||||||
|
@ -47,15 +48,15 @@ void type_env::bind_type(const std::string& type_name, type_ptr t) {
|
||||||
void type_env::generalize(const std::string& name, type_mgr& mgr) {
|
void type_env::generalize(const std::string& name, 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->forall.size() > 0) throw 0;
|
if(names_it->second.type->forall.size() > 0) throw 0;
|
||||||
|
|
||||||
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->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, name, 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->forall.push_back(free);
|
names_it->second.type->forall.push_back(free);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,21 @@
|
||||||
struct type_env;
|
struct type_env;
|
||||||
using type_env_ptr = std::shared_ptr<type_env>;
|
using type_env_ptr = std::shared_ptr<type_env>;
|
||||||
|
|
||||||
|
enum class visibility { global,local };
|
||||||
|
|
||||||
struct type_env {
|
struct type_env {
|
||||||
|
struct variable_data {
|
||||||
|
type_scheme_ptr type;
|
||||||
|
visibility vis;
|
||||||
|
|
||||||
|
variable_data()
|
||||||
|
: variable_data(nullptr, visibility::local) {}
|
||||||
|
variable_data(type_scheme_ptr t, visibility v)
|
||||||
|
: type(std::move(t)), vis(v) {}
|
||||||
|
};
|
||||||
|
|
||||||
type_env_ptr parent;
|
type_env_ptr parent;
|
||||||
std::map<std::string, type_scheme_ptr> names;
|
std::map<std::string, variable_data> names;
|
||||||
std::map<std::string, type_ptr> type_names;
|
std::map<std::string, type_ptr> type_names;
|
||||||
|
|
||||||
type_env(type_env_ptr p) : parent(std::move(p)) {}
|
type_env(type_env_ptr p) : parent(std::move(p)) {}
|
||||||
|
@ -20,8 +32,10 @@ struct type_env {
|
||||||
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;
|
||||||
type_ptr lookup_type(const std::string& name) const;
|
type_ptr lookup_type(const std::string& name) const;
|
||||||
void bind(const std::string& name, type_ptr t);
|
void bind(const std::string& name, type_ptr t,
|
||||||
void bind(const std::string& name, type_scheme_ptr t);
|
visibility v = visibility::local);
|
||||||
|
void bind(const std::string& name, type_scheme_ptr t,
|
||||||
|
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, type_mgr& mgr);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user