|
|
@ -2,6 +2,7 @@ |
|
|
|
#include <ostream> |
|
|
|
#include "binop.hpp" |
|
|
|
#include "error.hpp" |
|
|
|
#include "type_env.hpp" |
|
|
|
|
|
|
|
static void print_indent(int n, std::ostream& to) { |
|
|
|
while(n--) to << " "; |
|
|
@ -12,7 +13,11 @@ void ast_int::print(int indent, std::ostream& to) const { |
|
|
|
to << "INT: " << value << std::endl; |
|
|
|
} |
|
|
|
|
|
|
|
type_ptr ast_int::typecheck(type_mgr& mgr, const type_env& env) { |
|
|
|
void ast_int::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) { |
|
|
|
this->env = env; |
|
|
|
} |
|
|
|
|
|
|
|
type_ptr ast_int::typecheck(type_mgr& mgr) { |
|
|
|
return type_ptr(new type_base("Int")); |
|
|
|
} |
|
|
|
|
|
|
@ -25,8 +30,13 @@ void ast_lid::print(int indent, std::ostream& to) const { |
|
|
|
to << "LID: " << id << std::endl; |
|
|
|
} |
|
|
|
|
|
|
|
type_ptr ast_lid::typecheck(type_mgr& mgr, const type_env& env) { |
|
|
|
return env.lookup(id); |
|
|
|
void ast_lid::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) { |
|
|
|
this->env = env; |
|
|
|
if(env->lookup(id) == nullptr) into.insert(id); |
|
|
|
} |
|
|
|
|
|
|
|
type_ptr ast_lid::typecheck(type_mgr& mgr) { |
|
|
|
return env->lookup(id); |
|
|
|
} |
|
|
|
|
|
|
|
void ast_lid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const { |
|
|
@ -41,8 +51,12 @@ void ast_uid::print(int indent, std::ostream& to) const { |
|
|
|
to << "UID: " << id << std::endl; |
|
|
|
} |
|
|
|
|
|
|
|
type_ptr ast_uid::typecheck(type_mgr& mgr, const type_env& env) { |
|
|
|
return env.lookup(id); |
|
|
|
void ast_uid::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) { |
|
|
|
this->env = env; |
|
|
|
} |
|
|
|
|
|
|
|
type_ptr ast_uid::typecheck(type_mgr& mgr) { |
|
|
|
return env->lookup(id); |
|
|
|
} |
|
|
|
|
|
|
|
void ast_uid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const { |
|
|
@ -56,10 +70,16 @@ void ast_binop::print(int indent, std::ostream& to) const { |
|
|
|
right->print(indent + 1, to); |
|
|
|
} |
|
|
|
|
|
|
|
type_ptr ast_binop::typecheck(type_mgr& mgr, const type_env& env) { |
|
|
|
type_ptr ltype = left->typecheck(mgr, env); |
|
|
|
type_ptr rtype = right->typecheck(mgr, env); |
|
|
|
type_ptr ftype = env.lookup(op_name(op)); |
|
|
|
void ast_binop::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) { |
|
|
|
this->env = env; |
|
|
|
left->find_free(mgr, env, into); |
|
|
|
right->find_free(mgr, env, into); |
|
|
|
} |
|
|
|
|
|
|
|
type_ptr ast_binop::typecheck(type_mgr& mgr) { |
|
|
|
type_ptr ltype = left->typecheck(mgr); |
|
|
|
type_ptr rtype = right->typecheck(mgr); |
|
|
|
type_ptr ftype = env->lookup(op_name(op)); |
|
|
|
if(!ftype) throw type_error(std::string("unknown binary operator ") + op_name(op)); |
|
|
|
|
|
|
|
type_ptr return_type = mgr.new_type(); |
|
|
@ -86,9 +106,15 @@ void ast_app::print(int indent, std::ostream& to) const { |
|
|
|
right->print(indent + 1, to); |
|
|
|
} |
|
|
|
|
|
|
|
type_ptr ast_app::typecheck(type_mgr& mgr, const type_env& env) { |
|
|
|
type_ptr ltype = left->typecheck(mgr, env); |
|
|
|
type_ptr rtype = right->typecheck(mgr, env); |
|
|
|
void ast_app::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) { |
|
|
|
this->env = env; |
|
|
|
left->find_free(mgr, env, into); |
|
|
|
right->find_free(mgr, env, into); |
|
|
|
} |
|
|
|
|
|
|
|
type_ptr ast_app::typecheck(type_mgr& mgr) { |
|
|
|
type_ptr ltype = left->typecheck(mgr); |
|
|
|
type_ptr rtype = right->typecheck(mgr); |
|
|
|
|
|
|
|
type_ptr return_type = mgr.new_type(); |
|
|
|
type_ptr arrow = type_ptr(new type_arr(rtype, return_type)); |
|
|
@ -113,15 +139,24 @@ void ast_case::print(int indent, std::ostream& to) const { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
type_ptr ast_case::typecheck(type_mgr& mgr, const type_env& env) { |
|
|
|
void ast_case::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) { |
|
|
|
this->env = env; |
|
|
|
of->find_free(mgr, env, into); |
|
|
|
for(auto& branch : branches) { |
|
|
|
type_env_ptr new_env = type_scope(env); |
|
|
|
branch->pat->insert_bindings(mgr, new_env); |
|
|
|
branch->expr->find_free(mgr, new_env, into); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
type_ptr ast_case::typecheck(type_mgr& mgr) { |
|
|
|
type_var* var; |
|
|
|
type_ptr case_type = mgr.resolve(of->typecheck(mgr, env), var); |
|
|
|
type_ptr case_type = mgr.resolve(of->typecheck(mgr), var); |
|
|
|
type_ptr branch_type = mgr.new_type(); |
|
|
|
|
|
|
|
for(auto& branch : branches) { |
|
|
|
type_env new_env = env.scope(); |
|
|
|
branch->pat->match(case_type, mgr, new_env); |
|
|
|
type_ptr curr_branch_type = branch->expr->typecheck(mgr, new_env); |
|
|
|
branch->pat->typecheck(case_type, mgr, branch->expr->env); |
|
|
|
type_ptr curr_branch_type = branch->expr->typecheck(mgr); |
|
|
|
mgr.unify(branch_type, curr_branch_type); |
|
|
|
} |
|
|
|
|
|
|
@ -192,8 +227,12 @@ void pattern_var::print(std::ostream& to) const { |
|
|
|
to << var; |
|
|
|
} |
|
|
|
|
|
|
|
void pattern_var::match(type_ptr t, type_mgr& mgr, type_env& env) const { |
|
|
|
env.bind(var, t); |
|
|
|
void pattern_var::insert_bindings(type_mgr& mgr, type_env_ptr& env) const { |
|
|
|
env->bind(var, mgr.new_type()); |
|
|
|
} |
|
|
|
|
|
|
|
void pattern_var::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const { |
|
|
|
mgr.unify(env->lookup(var), t); |
|
|
|
} |
|
|
|
|
|
|
|
void pattern_constr::print(std::ostream& to) const { |
|
|
@ -203,17 +242,23 @@ void pattern_constr::print(std::ostream& to) const { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void pattern_constr::match(type_ptr t, type_mgr& mgr, type_env& env) const { |
|
|
|
type_ptr constructor_type = env.lookup(constr); |
|
|
|
void pattern_constr::insert_bindings(type_mgr& mgr, type_env_ptr& env) const { |
|
|
|
for(auto& param : params) { |
|
|
|
env->bind(param, mgr.new_type()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void pattern_constr::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const { |
|
|
|
type_ptr constructor_type = env->lookup(constr); |
|
|
|
if(!constructor_type) { |
|
|
|
throw type_error(std::string("pattern using unknown constructor ") + constr); |
|
|
|
} |
|
|
|
|
|
|
|
for(int i = 0; i < params.size(); i++) { |
|
|
|
for(auto& param : params) { |
|
|
|
type_arr* arr = dynamic_cast<type_arr*>(constructor_type.get()); |
|
|
|
if(!arr) throw type_error("too many parameters in constructor pattern"); |
|
|
|
|
|
|
|
env.bind(params[i], arr->left); |
|
|
|
mgr.unify(env->lookup(param), arr->left); |
|
|
|
constructor_type = arr->right; |
|
|
|
} |
|
|
|
|
|
|
|