Maybe finish the let/in code?

This commit is contained in:
Danila Fedorin 2020-06-01 00:23:41 -07:00
parent baf7427737
commit 522d196446
10 changed files with 241 additions and 158 deletions

View File

@ -14,11 +14,12 @@ void ast_int::print(int indent, std::ostream& to) const {
to << "INT: " << value << std::endl; to << "INT: " << value << std::endl;
} }
void ast_int::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) { void ast_int::find_free(std::set<std::string>& into) {
this->env = env;
} }
type_ptr ast_int::typecheck(type_mgr& mgr) { type_ptr ast_int::typecheck(type_mgr& mgr, type_env_ptr& env) {
this->env = env;
return type_ptr(new type_app(env->lookup_type("Int"))); return type_ptr(new type_app(env->lookup_type("Int")));
} }
@ -35,12 +36,12 @@ void ast_lid::print(int indent, std::ostream& to) const {
to << "LID: " << id << std::endl; to << "LID: " << id << std::endl;
} }
void ast_lid::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) { void ast_lid::find_free(std::set<std::string>& into) {
this->env = env; into.insert(id);
if(env->lookup(id) == nullptr) into.insert(id);
} }
type_ptr ast_lid::typecheck(type_mgr& mgr) { type_ptr ast_lid::typecheck(type_mgr& mgr, type_env_ptr& env) {
this->env = env;
return env->lookup(id)->instantiate(mgr); return env->lookup(id)->instantiate(mgr);
} }
@ -50,9 +51,9 @@ void ast_lid::translate(global_scope& scope) {
void ast_lid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const { void ast_lid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
into.push_back(instruction_ptr( into.push_back(instruction_ptr(
env->has_variable(id) ? (env->has_variable(id) && !this->env->is_global(id)) ?
(instruction*) new instruction_push(env->get_offset(id)) : (instruction*) new instruction_push(env->get_offset(id)) :
(instruction*) new instruction_pushglobal(id))); (instruction*) new instruction_pushglobal(this->env->get_mangled_name(id))));
} }
void ast_uid::print(int indent, std::ostream& to) const { void ast_uid::print(int indent, std::ostream& to) const {
@ -60,11 +61,12 @@ void ast_uid::print(int indent, std::ostream& to) const {
to << "UID: " << id << std::endl; to << "UID: " << id << std::endl;
} }
void ast_uid::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) { void ast_uid::find_free(std::set<std::string>& into) {
this->env = env;
} }
type_ptr ast_uid::typecheck(type_mgr& mgr) { type_ptr ast_uid::typecheck(type_mgr& mgr, type_env_ptr& env) {
this->env = env;
return env->lookup(id)->instantiate(mgr); return env->lookup(id)->instantiate(mgr);
} }
@ -73,7 +75,8 @@ void ast_uid::translate(global_scope& scope) {
} }
void ast_uid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const { void ast_uid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
into.push_back(instruction_ptr(new instruction_pushglobal(id))); into.push_back(instruction_ptr(
new instruction_pushglobal(this->env->get_mangled_name(id))));
} }
void ast_binop::print(int indent, std::ostream& to) const { void ast_binop::print(int indent, std::ostream& to) const {
@ -83,15 +86,15 @@ void ast_binop::print(int indent, std::ostream& to) const {
right->print(indent + 1, to); right->print(indent + 1, to);
} }
void ast_binop::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) { void ast_binop::find_free(std::set<std::string>& into) {
this->env = env; left->find_free(into);
left->find_free(mgr, env, into); right->find_free(into);
right->find_free(mgr, env, into);
} }
type_ptr ast_binop::typecheck(type_mgr& mgr) { type_ptr ast_binop::typecheck(type_mgr& mgr, type_env_ptr& env) {
type_ptr ltype = left->typecheck(mgr); this->env = env;
type_ptr rtype = right->typecheck(mgr); type_ptr ltype = left->typecheck(mgr, env);
type_ptr rtype = right->typecheck(mgr, env);
type_ptr ftype = env->lookup(op_name(op))->instantiate(mgr); type_ptr ftype = env->lookup(op_name(op))->instantiate(mgr);
if(!ftype) throw type_error(std::string("unknown binary operator ") + op_name(op)); if(!ftype) throw type_error(std::string("unknown binary operator ") + op_name(op));
@ -124,15 +127,15 @@ void ast_app::print(int indent, std::ostream& to) const {
right->print(indent + 1, to); right->print(indent + 1, to);
} }
void ast_app::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) { void ast_app::find_free(std::set<std::string>& into) {
this->env = env; left->find_free(into);
left->find_free(mgr, env, into); right->find_free(into);
right->find_free(mgr, env, into);
} }
type_ptr ast_app::typecheck(type_mgr& mgr) { type_ptr ast_app::typecheck(type_mgr& mgr, type_env_ptr& env) {
type_ptr ltype = left->typecheck(mgr); this->env = env;
type_ptr rtype = right->typecheck(mgr); type_ptr ltype = left->typecheck(mgr, env);
type_ptr rtype = right->typecheck(mgr, env);
type_ptr return_type = mgr.new_type(); type_ptr return_type = mgr.new_type();
type_ptr arrow = type_ptr(new type_arr(rtype, return_type)); type_ptr arrow = type_ptr(new type_arr(rtype, return_type));
@ -162,24 +165,30 @@ void ast_case::print(int indent, std::ostream& to) const {
} }
} }
void ast_case::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) { void ast_case::find_free(std::set<std::string>& into) {
this->env = env; of->find_free(into);
of->find_free(mgr, env, into);
for(auto& branch : branches) { for(auto& branch : branches) {
type_env_ptr new_env = type_scope(env); std::set<std::string> free_in_branch;
branch->pat->insert_bindings(mgr, new_env); std::set<std::string> pattern_variables;
branch->expr->find_free(mgr, new_env, into); branch->pat->find_variables(pattern_variables);
branch->expr->find_free(free_in_branch);
for(auto& free : free_in_branch) {
if(pattern_variables.find(free) == pattern_variables.end())
into.insert(free);
}
} }
} }
type_ptr ast_case::typecheck(type_mgr& mgr) { type_ptr ast_case::typecheck(type_mgr& mgr, type_env_ptr& env) {
this->env = env;
type_var* var; type_var* var;
type_ptr case_type = mgr.resolve(of->typecheck(mgr), var); type_ptr case_type = mgr.resolve(of->typecheck(mgr, env), var);
type_ptr branch_type = mgr.new_type(); type_ptr branch_type = mgr.new_type();
for(auto& branch : branches) { for(auto& branch : branches) {
branch->pat->typecheck(case_type, mgr, branch->expr->env); type_env_ptr new_env = type_scope(env);
type_ptr curr_branch_type = branch->expr->typecheck(mgr); branch->pat->typecheck(case_type, mgr, new_env);
type_ptr curr_branch_type = branch->expr->typecheck(mgr, new_env);
mgr.unify(branch_type, curr_branch_type); mgr.unify(branch_type, curr_branch_type);
} }
@ -262,36 +271,46 @@ void ast_let::print(int indent, std::ostream& to) const {
in->print(indent + 1, to); in->print(indent + 1, to);
} }
void ast_let::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) { void ast_let::find_free(std::set<std::string>& into) {
this->env = env; definitions.find_free(into);
definitions.find_free(mgr, env, into);
std::set<std::string> all_free; std::set<std::string> all_free;
in->find_free(mgr, definitions.env, all_free); in->find_free(all_free);
for(auto& free_var : all_free) { for(auto& free_var : all_free) {
if(definitions.defs_defn.find(free_var) == definitions.defs_defn.end()) if(definitions.defs_defn.find(free_var) == definitions.defs_defn.end())
into.insert(free_var); into.insert(free_var);
} }
} }
type_ptr ast_let::typecheck(type_mgr& mgr) { type_ptr ast_let::typecheck(type_mgr& mgr, type_env_ptr& env) {
definitions.typecheck(mgr); this->env = env;
return in->typecheck(mgr); definitions.typecheck(mgr, env);
return in->typecheck(mgr, definitions.env);
} }
void ast_let::translate(global_scope& scope) { void ast_let::translate(global_scope& scope) {
for(auto& def : definitions.defs_data) {
def.second->into_globals(scope);
}
for(auto& def : definitions.defs_defn) { for(auto& def : definitions.defs_defn) {
size_t original_params = def.second->params.size(); size_t original_params = def.second->params.size();
std::string original_name = def.second->name; std::string original_name = def.second->name;
auto& global_definition = def.second->into_global(scope); auto& global_definition = def.second->into_global(scope);
size_t captured = global_definition->params.size() - original_params; size_t captured = global_definition.params.size() - original_params;
ast_ptr global_app(new ast_lid(global_definition->name)); type_env_ptr mangled_env = type_scope(env);
for(auto& param : global_definition->params) { mangled_env->bind(def.first, env->lookup(def.first), visibility::global);
mangled_env->set_mangled_name(def.first, global_definition.name);
ast_ptr global_app(new ast_lid(global_definition.name));
global_app->env = mangled_env;
for(auto& param : global_definition.params) {
if(!(captured--)) break; if(!(captured--)) break;
ast_ptr new_arg(new ast_lid(param)); ast_ptr new_arg(new ast_lid(param));
new_arg->env = env;
global_app = ast_ptr(new ast_app(std::move(global_app), std::move(new_arg))); global_app = ast_ptr(new ast_app(std::move(global_app), std::move(new_arg)));
global_app->env = env;
} }
translated_definitions.push_back({ global_definition->name, std::move(global_app) }); translated_definitions.push_back({ def.first, std::move(global_app) });
} }
in->translate(scope); in->translate(scope);
} }
@ -308,18 +327,19 @@ void ast_let::compile(const env_ptr& env, std::vector<instruction_ptr>& into) co
into.push_back(instruction_ptr(new instruction_update(offset--))); into.push_back(instruction_ptr(new instruction_update(offset--)));
} }
in->compile(new_env, into); in->compile(new_env, into);
into.push_back(instruction_ptr(new instruction_slide(translated_definitions.size())));
} }
void pattern_var::print(std::ostream& to) const { void pattern_var::print(std::ostream& to) const {
to << var; to << var;
} }
void pattern_var::insert_bindings(type_mgr& mgr, type_env_ptr& env) const { void pattern_var::find_variables(std::set<std::string>& into) const {
env->bind(var, mgr.new_type()); into.insert(var);
} }
void pattern_var::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const { void pattern_var::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const {
mgr.unify(env->lookup(var)->instantiate(mgr), t); env->bind(var, t);
} }
void pattern_constr::print(std::ostream& to) const { void pattern_constr::print(std::ostream& to) const {
@ -329,10 +349,8 @@ void pattern_constr::print(std::ostream& to) const {
} }
} }
void pattern_constr::insert_bindings(type_mgr& mgr, type_env_ptr& env) const { void pattern_constr::find_variables(std::set<std::string>& into) const {
for(auto& param : params) { into.insert(params.begin(), params.end());
env->bind(param, mgr.new_type());
}
} }
void pattern_constr::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const { void pattern_constr::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const {
@ -345,7 +363,7 @@ void pattern_constr::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) con
type_arr* arr = dynamic_cast<type_arr*>(constructor_type.get()); type_arr* arr = dynamic_cast<type_arr*>(constructor_type.get());
if(!arr) throw type_error("too many parameters in constructor pattern"); if(!arr) throw type_error("too many parameters in constructor pattern");
mgr.unify(env->lookup(param)->instantiate(mgr), arr->left); env->bind(param, arr->left);
constructor_type = arr->right; constructor_type = arr->right;
} }

View File

@ -16,9 +16,8 @@ struct ast {
virtual ~ast() = default; virtual ~ast() = default;
virtual void print(int indent, std::ostream& to) const = 0; virtual void print(int indent, std::ostream& to) const = 0;
virtual void find_free(type_mgr& mgr, virtual void find_free(std::set<std::string>& into) = 0;
type_env_ptr& env, std::set<std::string>& into) = 0; virtual type_ptr typecheck(type_mgr& mgr, type_env_ptr& env) = 0;
virtual type_ptr typecheck(type_mgr& mgr) = 0;
virtual void translate(global_scope& scope) = 0; virtual void translate(global_scope& scope) = 0;
virtual void compile(const env_ptr& env, virtual void compile(const env_ptr& env,
std::vector<instruction_ptr>& into) const = 0; std::vector<instruction_ptr>& into) const = 0;
@ -30,7 +29,7 @@ struct pattern {
virtual ~pattern() = default; virtual ~pattern() = default;
virtual void print(std::ostream& to) const = 0; virtual void print(std::ostream& to) const = 0;
virtual void insert_bindings(type_mgr& mgr, type_env_ptr& env) const = 0; virtual void find_variables(std::set<std::string>& into) const = 0;
virtual void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const = 0; virtual void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const = 0;
}; };
@ -53,8 +52,8 @@ struct ast_int : public ast {
: value(v) {} : value(v) {}
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into); void find_free(std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env);
void translate(global_scope& scope); void translate(global_scope& scope);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const; void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
@ -66,8 +65,8 @@ struct ast_lid : public ast {
: id(std::move(i)) {} : id(std::move(i)) {}
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into); void find_free(std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env);
void translate(global_scope& scope); void translate(global_scope& scope);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const; void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
@ -79,8 +78,8 @@ struct ast_uid : public ast {
: id(std::move(i)) {} : id(std::move(i)) {}
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into); void find_free(std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env);
void translate(global_scope& scope); void translate(global_scope& scope);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const; void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
@ -94,8 +93,8 @@ struct ast_binop : public ast {
: op(o), left(std::move(l)), right(std::move(r)) {} : op(o), left(std::move(l)), right(std::move(r)) {}
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into); void find_free(std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env);
void translate(global_scope& scope); void translate(global_scope& scope);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const; void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
@ -108,8 +107,8 @@ struct ast_app : public ast {
: left(std::move(l)), right(std::move(r)) {} : left(std::move(l)), right(std::move(r)) {}
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into); void find_free(std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env);
void translate(global_scope& scope); void translate(global_scope& scope);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const; void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
@ -123,8 +122,8 @@ struct ast_case : public ast {
: of(std::move(o)), branches(std::move(b)) {} : of(std::move(o)), branches(std::move(b)) {}
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into); void find_free(std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env);
void translate(global_scope& scope); void translate(global_scope& scope);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const; void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
@ -141,8 +140,8 @@ struct ast_let : public ast {
: definitions(std::move(g)), in(std::move(i)) {} : definitions(std::move(g)), in(std::move(i)) {}
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into); void find_free(std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env);
void translate(global_scope& scope); void translate(global_scope& scope);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const; void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
@ -154,7 +153,7 @@ struct pattern_var : public pattern {
: var(std::move(v)) {} : var(std::move(v)) {}
void print(std::ostream &to) const; void print(std::ostream &to) const;
void insert_bindings(type_mgr& mgr, type_env_ptr& env) const; void find_variables(std::set<std::string>& into) const;
void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const; void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const;
}; };
@ -166,6 +165,6 @@ struct pattern_constr : public pattern {
: constr(std::move(c)), params(std::move(p)) {} : constr(std::move(c)), params(std::move(p)) {}
void print(std::ostream &to) const; void print(std::ostream &to) const;
virtual void insert_bindings(type_mgr& mgr, type_env_ptr& env) const; void find_variables(std::set<std::string>& into) const;
virtual void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const; virtual void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const;
}; };

View File

@ -10,9 +10,15 @@
#include <llvm/IR/Function.h> #include <llvm/IR/Function.h>
#include <llvm/IR/Type.h> #include <llvm/IR/Type.h>
void definition_defn::find_free(type_mgr& mgr, type_env_ptr& env) { void definition_defn::find_free() {
this->env = env; body->find_free(free_variables);
for(auto& param : params) {
free_variables.erase(param);
}
}
void definition_defn::insert_types(type_mgr& mgr, type_env_ptr& env, visibility v) {
this->env = env;
var_env = type_scope(env); var_env = type_scope(env);
return_type = mgr.new_type(); return_type = mgr.new_type();
full_type = return_type; full_type = return_type;
@ -22,29 +28,24 @@ void definition_defn::find_free(type_mgr& mgr, type_env_ptr& env) {
full_type = type_ptr(new type_arr(param_type, full_type)); full_type = type_ptr(new type_arr(param_type, full_type));
var_env->bind(*it, param_type); var_env->bind(*it, param_type);
} }
body->find_free(mgr, var_env, free_variables);
}
void definition_defn::insert_types(type_mgr& mgr, visibility v) {
env->bind(name, full_type, v); env->bind(name, full_type, v);
} }
void definition_defn::typecheck(type_mgr& mgr) { void definition_defn::typecheck(type_mgr& mgr) {
type_ptr body_type = body->typecheck(mgr); type_ptr body_type = body->typecheck(mgr, var_env);
mgr.unify(return_type, body_type); mgr.unify(return_type, body_type);
} }
global_definition_ptr& definition_defn::into_global(global_scope& scope) { global_function& definition_defn::into_global(global_scope& scope) {
std::vector<std::string> all_params; std::vector<std::string> all_params;
for(auto& free : free_variables) { for(auto& free : free_variables) {
if(env->is_global(free)) continue; if(env->is_global(free)) continue;
all_params.push_back(free); all_params.push_back(free);
} }
all_params.insert(all_params.end(), params.begin(), params.end()); all_params.insert(all_params.end(), params.begin(), params.end());
translate(body, scope); body->translate(scope);
return scope.add_definition(name, std::move(all_params), std::move(body)); return scope.add_function(name, std::move(all_params), std::move(body));
} }
void definition_data::insert_types(type_env_ptr& env) { void definition_data::insert_types(type_env_ptr& env) {
@ -82,28 +83,17 @@ void definition_data::insert_constructors() const {
} }
} }
void definition_data::generate_llvm(llvm_context& ctx) { void definition_data::into_globals(global_scope& scope) {
for(auto& constructor : constructors) { for(auto& constructor : constructors) {
auto new_function = global_constructor& c = scope.add_constructor(
ctx.create_custom_function(constructor->name, constructor->types.size()); constructor->name, constructor->tag, constructor->types.size());
std::vector<instruction_ptr> instructions; env->set_mangled_name(constructor->name, c.name);
instructions.push_back(instruction_ptr(
new instruction_pack(constructor->tag, constructor->types.size())
));
instructions.push_back(instruction_ptr(new instruction_update(0)));
ctx.builder.SetInsertPoint(&new_function->getEntryBlock());
for (auto& instruction : instructions) {
instruction->gen_llvm(ctx, new_function);
}
ctx.builder.CreateRetVoid();
} }
} }
void definition_group::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) { void definition_group::find_free(std::set<std::string>& into) {
this->env = type_scope(env);
for(auto& def_pair : defs_defn) { for(auto& def_pair : defs_defn) {
def_pair.second->find_free(mgr, env); def_pair.second->find_free();
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);
@ -114,9 +104,11 @@ void definition_group::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std:
} }
} }
void definition_group::typecheck(type_mgr& mgr) { void definition_group::typecheck(type_mgr& mgr, type_env_ptr& env) {
this->env = type_scope(env);
for(auto& def_data : defs_data) { for(auto& def_data : defs_data) {
def_data.second->insert_types(env); def_data.second->insert_types(this->env);
} }
for(auto& def_data : defs_data) { for(auto& def_data : defs_data) {
def_data.second->insert_constructors(); def_data.second->insert_constructors();
@ -125,7 +117,7 @@ void definition_group::typecheck(type_mgr& mgr) {
function_graph dependency_graph; function_graph dependency_graph;
for(auto& def_defn : defs_defn) { for(auto& def_defn : defs_defn) {
def_defn.second->find_free(mgr, env); def_defn.second->find_free();
dependency_graph.add_function(def_defn.second->name); dependency_graph.add_function(def_defn.second->name);
for(auto& dependency : def_defn.second->nearby_variables) { for(auto& dependency : def_defn.second->nearby_variables) {
@ -140,14 +132,14 @@ 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, vis); def_defn->insert_types(mgr, this->env, 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;
def_defn->typecheck(mgr); def_defn->typecheck(mgr);
} }
for(auto& def_defnn_name : group->members) { for(auto& def_defnn_name : group->members) {
env->generalize(def_defnn_name, mgr); this->env->generalize(def_defnn_name, mgr);
} }
} }
} }

View File

@ -40,11 +40,11 @@ struct definition_defn {
} }
void find_free(type_mgr& mgr, type_env_ptr& env); void find_free();
void insert_types(type_mgr& mgr, visibility v); void insert_types(type_mgr& mgr, type_env_ptr& env, visibility v);
void typecheck(type_mgr& mgr); void typecheck(type_mgr& mgr);
global_definition_ptr& into_global(global_scope& scope); global_function& into_global(global_scope& scope);
}; };
using definition_defn_ptr = std::unique_ptr<definition_defn>; using definition_defn_ptr = std::unique_ptr<definition_defn>;
@ -64,7 +64,8 @@ struct definition_data {
void insert_types(type_env_ptr& env); void insert_types(type_env_ptr& env);
void insert_constructors() const; void insert_constructors() const;
void generate_llvm(llvm_context& ctx);
void into_globals(global_scope& scope);
}; };
using definition_data_ptr = std::unique_ptr<definition_data>; using definition_data_ptr = std::unique_ptr<definition_data>;
@ -77,6 +78,6 @@ struct definition_group {
definition_group(visibility v = visibility::local) : vis(v) {} 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(std::set<std::string>& into);
void typecheck(type_mgr& mgr); void typecheck(type_mgr& mgr, type_env_ptr& env);
}; };

View File

@ -1,7 +1,7 @@
#include "global_scope.hpp" #include "global_scope.hpp"
#include "ast.hpp" #include "ast.hpp"
void global_definition::compile() { void global_function::compile() {
env_ptr new_env = env_ptr(new env_offset(0, nullptr)); env_ptr new_env = env_ptr(new env_offset(0, nullptr));
for(auto it = params.rbegin(); it != params.rend(); it++) { for(auto it = params.rbegin(); it != params.rend(); it++) {
new_env = env_ptr(new env_var(*it, new_env)); new_env = env_ptr(new env_var(*it, new_env));
@ -11,11 +11,11 @@ void global_definition::compile() {
instructions.push_back(instruction_ptr(new instruction_pop(params.size()))); instructions.push_back(instruction_ptr(new instruction_pop(params.size())));
} }
void global_definition::declare_llvm(llvm_context& ctx) { void global_function::declare_llvm(llvm_context& ctx) {
generated_function = ctx.create_custom_function(name, params.size()); generated_function = ctx.create_custom_function(name, params.size());
} }
void global_definition::generate_llvm(llvm_context& ctx) { void global_function::generate_llvm(llvm_context& ctx) {
ctx.builder.SetInsertPoint(&generated_function->getEntryBlock()); ctx.builder.SetInsertPoint(&generated_function->getEntryBlock());
for(auto& instruction : instructions) { for(auto& instruction : instructions) {
instruction->gen_llvm(ctx, generated_function); instruction->gen_llvm(ctx, generated_function);
@ -23,7 +23,50 @@ void global_definition::generate_llvm(llvm_context& ctx) {
ctx.builder.CreateRetVoid(); ctx.builder.CreateRetVoid();
} }
global_definition_ptr& global_scope::add_definition(std::string n, std::vector<std::string> ps, ast_ptr b) { void global_constructor::generate_llvm(llvm_context& ctx) {
auto new_function =
ctx.create_custom_function(name, arity);
std::vector<instruction_ptr> instructions;
instructions.push_back(instruction_ptr(new instruction_pack(tag, arity)));
instructions.push_back(instruction_ptr(new instruction_update(0)));
ctx.builder.SetInsertPoint(&new_function->getEntryBlock());
for (auto& instruction : instructions) {
instruction->gen_llvm(ctx, new_function);
}
ctx.builder.CreateRetVoid();
}
global_function& global_scope::add_function(std::string n, std::vector<std::string> ps, ast_ptr b) {
global_function* new_function = new global_function(mangle_name(n), std::move(ps), std::move(b));
functions.push_back(global_function_ptr(new_function));
return *new_function;
}
global_constructor& global_scope::add_constructor(std::string n, int8_t t, size_t a) {
global_constructor* new_constructor = new global_constructor(mangle_name(n), t, a);
constructors.push_back(global_constructor_ptr(new_constructor));
return *new_constructor;
}
void global_scope::compile() {
for(auto& function : functions) {
function->compile();
}
}
void global_scope::generate_llvm(llvm_context& ctx) {
for(auto& constructor : constructors) {
constructor->generate_llvm(ctx);
}
for(auto& function : functions) {
function->declare_llvm(ctx);
}
for(auto& function : functions) {
function->generate_llvm(ctx);
}
}
std::string global_scope::mangle_name(const std::string& n) {
auto occurence_it = occurence_count.find(n); auto occurence_it = occurence_count.find(n);
int occurence = 0; int occurence = 0;
if(occurence_it != occurence_count.end()) { if(occurence_it != occurence_count.end()) {
@ -36,8 +79,5 @@ global_definition_ptr& global_scope::add_definition(std::string n, std::vector<s
final_name += "_"; final_name += "_";
final_name += std::to_string(occurence); final_name += std::to_string(occurence);
} }
return final_name;
definitions.push_back(global_definition_ptr(
new global_definition(final_name, std::move(ps), std::move(b))));
return *definitions.rbegin();
} }

View File

@ -9,6 +9,10 @@ struct ast;
using ast_ptr = std::unique_ptr<ast>; using ast_ptr = std::unique_ptr<ast>;
struct global_definition { struct global_definition {
virtual void generate_llvm(llvm_context& ctx) = 0;
};
struct global_function : global_definition {
std::string name; std::string name;
std::vector<std::string> params; std::vector<std::string> params;
ast_ptr body; ast_ptr body;
@ -16,7 +20,7 @@ struct global_definition {
std::vector<instruction_ptr> instructions; std::vector<instruction_ptr> instructions;
llvm::Function* generated_function; llvm::Function* generated_function;
global_definition(std::string n, std::vector<std::string> ps, ast_ptr b) global_function(std::string n, std::vector<std::string> ps, ast_ptr b)
: name(std::move(n)), params(std::move(ps)), body(std::move(b)) {} : name(std::move(n)), params(std::move(ps)), body(std::move(b)) {}
void compile(); void compile();
@ -24,11 +28,32 @@ struct global_definition {
void generate_llvm(llvm_context& ctx); void generate_llvm(llvm_context& ctx);
}; };
using global_definition_ptr = std::unique_ptr<global_definition>; using global_function_ptr = std::unique_ptr<global_function>;
struct global_constructor : global_definition {
std::string name;
int8_t tag;
size_t arity;
global_constructor(std::string n, int8_t t, size_t a)
: name(std::move(n)), tag(t), arity(a) {}
void generate_llvm(llvm_context& ctx);
};
using global_constructor_ptr = std::unique_ptr<global_constructor>;
struct global_scope { struct global_scope {
std::map<std::string, int> occurence_count; std::map<std::string, int> occurence_count;
std::vector<global_definition_ptr> definitions; std::vector<global_function_ptr> functions;
std::vector<global_constructor_ptr> constructors;
global_definition_ptr& add_definition(std::string n, std::vector<std::string> ps, ast_ptr b); global_function& add_function(std::string n, std::vector<std::string> ps, ast_ptr b);
global_constructor& add_constructor(std::string n, int8_t t, size_t a);
void compile();
void generate_llvm(llvm_context& ctx);
private:
std::string mangle_name(const std::string& n);
}; };

View File

@ -39,8 +39,8 @@ void typecheck_program(
env->bind("/", binop_type, visibility::global); 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(free);
defs.typecheck(mgr); defs.typecheck(mgr, env);
for(auto& pair : defs.env->names) { for(auto& pair : defs.env->names) {
std::cout << pair.first << ": "; std::cout << pair.first << ": ";
@ -49,15 +49,16 @@ void typecheck_program(
} }
} }
void compile_program(const std::map<std::string, definition_defn_ptr>& defs_defn) { global_scope translate_program(definition_group& group) {
for(auto& def_defn : defs_defn) { global_scope scope;
def_defn.second->compile(); for(auto& data : group.defs_data) {
data.second->into_globals(scope);
for(auto& instruction : def_defn.second->instructions) {
instruction->print(0, std::cout);
}
std::cout << std::endl;
} }
for(auto& defn : group.defs_defn) {
auto& function = defn.second->into_global(scope);
function.body->env->parent->set_mangled_name(defn.first, function.name);
}
return scope;
} }
void gen_llvm_internal_op(llvm_context& ctx, binop op) { void gen_llvm_internal_op(llvm_context& ctx, binop op) {
@ -117,24 +118,14 @@ void output_llvm(llvm_context& ctx, const std::string& filename) {
} }
} }
void gen_llvm( void gen_llvm(global_scope& scope) {
const std::map<std::string, definition_data_ptr>& defs_data,
const std::map<std::string, definition_defn_ptr>& defs_defn) {
llvm_context ctx; llvm_context ctx;
gen_llvm_internal_op(ctx, PLUS); gen_llvm_internal_op(ctx, PLUS);
gen_llvm_internal_op(ctx, MINUS); gen_llvm_internal_op(ctx, MINUS);
gen_llvm_internal_op(ctx, TIMES); gen_llvm_internal_op(ctx, TIMES);
gen_llvm_internal_op(ctx, DIVIDE); gen_llvm_internal_op(ctx, DIVIDE);
for(auto& def_data : defs_data) { scope.generate_llvm(ctx);
def_data.second->generate_llvm(ctx);
}
for(auto& def_defn : defs_defn) {
def_defn.second->declare_llvm(ctx);
}
for(auto& def_defn : defs_defn) {
def_defn.second->generate_llvm(ctx);
}
ctx.module.print(llvm::outs(), nullptr); ctx.module.print(llvm::outs(), nullptr);
output_llvm(ctx, "program.o"); output_llvm(ctx, "program.o");
@ -155,8 +146,9 @@ int main() {
} }
try { try {
typecheck_program(global_defs, mgr, env); typecheck_program(global_defs, mgr, env);
compile_program(global_defs.defs_defn); global_scope scope = translate_program(global_defs);
gen_llvm(global_defs.defs_data, global_defs.defs_defn); scope.compile();
gen_llvm(scope);
} catch(unification_error& err) { } catch(unification_error& err) {
std::cout << "failed to unify types: " << std::endl; std::cout << "failed to unify types: " << std::endl;
std::cout << " (1) \033[34m"; std::cout << " (1) \033[34m";

View File

@ -7,7 +7,7 @@
#include "parser.hpp" #include "parser.hpp"
#include "parsed_type.hpp" #include "parsed_type.hpp"
definition_group global_defs(visibility::global); definition_group global_defs;
extern yy::parser::symbol_type yylex(); extern yy::parser::symbol_type yylex();
@ -56,7 +56,7 @@ extern yy::parser::symbol_type yylex();
%% %%
program program
: definitions { global_defs = std::move($1); } : definitions { global_defs = std::move($1); global_defs.vis = visibility::global; }
; ;
definitions definitions

View File

@ -31,6 +31,19 @@ bool type_env::is_global(const std::string& name) const {
return false; return false;
} }
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;
}
type_ptr type_env::lookup_type(const std::string& name) const { type_ptr type_env::lookup_type(const std::string& name) const {
auto it = type_names.find(name); auto it = type_names.find(name);
if(it != type_names.end()) return it->second; if(it != type_names.end()) return it->second;
@ -40,11 +53,11 @@ type_ptr type_env::lookup_type(const std::string& name) const {
void type_env::bind(const std::string& name, type_ptr t, visibility v) { void type_env::bind(const std::string& name, type_ptr t, visibility v) {
type_scheme_ptr new_scheme(new type_scheme(std::move(t))); type_scheme_ptr new_scheme(new type_scheme(std::move(t)));
names[name] = variable_data(std::move(new_scheme), v); names[name] = variable_data(std::move(new_scheme), v, "");
} }
void type_env::bind(const std::string& name, type_scheme_ptr t, visibility v) { void type_env::bind(const std::string& name, type_scheme_ptr t, visibility v) {
names[name] = variable_data(std::move(t), v); 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) {

View File

@ -13,11 +13,12 @@ struct type_env {
struct variable_data { struct variable_data {
type_scheme_ptr type; type_scheme_ptr type;
visibility vis; visibility vis;
std::string mangled_name;
variable_data() variable_data()
: variable_data(nullptr, visibility::local) {} : variable_data(nullptr, visibility::local, "") {}
variable_data(type_scheme_ptr t, visibility v) variable_data(type_scheme_ptr t, visibility v, std::string n)
: type(std::move(t)), vis(v) {} : type(std::move(t)), vis(v), mangled_name(std::move(n)) {}
}; };
type_env_ptr parent; type_env_ptr parent;
@ -32,6 +33,8 @@ 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;
bool is_global(const std::string& name) const; bool is_global(const std::string& name) const;
void set_mangled_name(const std::string& name, const std::string& mangled);
const std::string& get_mangled_name(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,
visibility v = visibility::local); visibility v = visibility::local);