From 522d1964466ee5c1780fb01a31ca1ea223aff29a Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Mon, 1 Jun 2020 00:23:41 -0700 Subject: [PATCH] Maybe finish the let/in code? --- 12/ast.cpp | 130 +++++++++++++++++++++++++------------------- 12/ast.hpp | 39 +++++++------ 12/definition.cpp | 58 +++++++++----------- 12/definition.hpp | 13 +++-- 12/global_scope.cpp | 56 ++++++++++++++++--- 12/global_scope.hpp | 33 +++++++++-- 12/main.cpp | 40 ++++++-------- 12/parser.y | 4 +- 12/type_env.cpp | 17 +++++- 12/type_env.hpp | 9 ++- 10 files changed, 241 insertions(+), 158 deletions(-) diff --git a/12/ast.cpp b/12/ast.cpp index 862273f..602d7fb 100644 --- a/12/ast.cpp +++ b/12/ast.cpp @@ -14,11 +14,12 @@ void ast_int::print(int indent, std::ostream& to) const { to << "INT: " << value << std::endl; } -void ast_int::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; +void ast_int::find_free(std::set& into) { + } -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"))); } @@ -35,12 +36,12 @@ void ast_lid::print(int indent, std::ostream& to) const { to << "LID: " << id << std::endl; } -void ast_lid::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; - if(env->lookup(id) == nullptr) into.insert(id); +void ast_lid::find_free(std::set& into) { + 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); } @@ -50,9 +51,9 @@ void ast_lid::translate(global_scope& scope) { void ast_lid::compile(const env_ptr& env, std::vector& into) const { 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_pushglobal(id))); + (instruction*) new instruction_pushglobal(this->env->get_mangled_name(id)))); } 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; } -void ast_uid::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; +void ast_uid::find_free(std::set& into) { + } -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); } @@ -73,7 +75,8 @@ void ast_uid::translate(global_scope& scope) { } void ast_uid::compile(const env_ptr& env, std::vector& 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 { @@ -83,15 +86,15 @@ void ast_binop::print(int indent, std::ostream& to) const { right->print(indent + 1, to); } -void ast_binop::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; - left->find_free(mgr, env, into); - right->find_free(mgr, env, into); +void ast_binop::find_free(std::set& into) { + left->find_free(into); + right->find_free(into); } -type_ptr ast_binop::typecheck(type_mgr& mgr) { - type_ptr ltype = left->typecheck(mgr); - type_ptr rtype = right->typecheck(mgr); +type_ptr ast_binop::typecheck(type_mgr& mgr, type_env_ptr& env) { + this->env = env; + type_ptr ltype = left->typecheck(mgr, env); + type_ptr rtype = right->typecheck(mgr, env); type_ptr ftype = env->lookup(op_name(op))->instantiate(mgr); 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); } -void ast_app::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; - left->find_free(mgr, env, into); - right->find_free(mgr, env, into); +void ast_app::find_free(std::set& into) { + left->find_free(into); + right->find_free(into); } -type_ptr ast_app::typecheck(type_mgr& mgr) { - type_ptr ltype = left->typecheck(mgr); - type_ptr rtype = right->typecheck(mgr); +type_ptr ast_app::typecheck(type_mgr& mgr, type_env_ptr& env) { + this->env = env; + type_ptr ltype = left->typecheck(mgr, env); + type_ptr rtype = right->typecheck(mgr, env); type_ptr return_type = mgr.new_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& into) { - this->env = env; - of->find_free(mgr, env, into); +void ast_case::find_free(std::set& into) { + of->find_free(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); + std::set free_in_branch; + std::set pattern_variables; + 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_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(); for(auto& branch : branches) { - branch->pat->typecheck(case_type, mgr, branch->expr->env); - type_ptr curr_branch_type = branch->expr->typecheck(mgr); + type_env_ptr new_env = type_scope(env); + 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); } @@ -262,36 +271,46 @@ void ast_let::print(int indent, std::ostream& to) const { in->print(indent + 1, to); } -void ast_let::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; - definitions.find_free(mgr, env, into); +void ast_let::find_free(std::set& into) { + definitions.find_free(into); std::set all_free; - in->find_free(mgr, definitions.env, all_free); + in->find_free(all_free); for(auto& free_var : all_free) { if(definitions.defs_defn.find(free_var) == definitions.defs_defn.end()) into.insert(free_var); } } -type_ptr ast_let::typecheck(type_mgr& mgr) { - definitions.typecheck(mgr); - return in->typecheck(mgr); +type_ptr ast_let::typecheck(type_mgr& mgr, type_env_ptr& env) { + this->env = env; + definitions.typecheck(mgr, env); + return in->typecheck(mgr, definitions.env); } void ast_let::translate(global_scope& scope) { + for(auto& def : definitions.defs_data) { + def.second->into_globals(scope); + } for(auto& def : definitions.defs_defn) { size_t original_params = def.second->params.size(); std::string original_name = def.second->name; 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)); - for(auto& param : global_definition->params) { + type_env_ptr mangled_env = type_scope(env); + 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; 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->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); } @@ -308,18 +327,19 @@ void ast_let::compile(const env_ptr& env, std::vector& into) co into.push_back(instruction_ptr(new instruction_update(offset--))); } in->compile(new_env, into); + into.push_back(instruction_ptr(new instruction_slide(translated_definitions.size()))); } void pattern_var::print(std::ostream& to) const { to << var; } -void pattern_var::insert_bindings(type_mgr& mgr, type_env_ptr& env) const { - env->bind(var, mgr.new_type()); +void pattern_var::find_variables(std::set& into) const { + into.insert(var); } 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 { @@ -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 { - for(auto& param : params) { - env->bind(param, mgr.new_type()); - } +void pattern_constr::find_variables(std::set& into) const { + into.insert(params.begin(), params.end()); } 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(constructor_type.get()); 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; } diff --git a/12/ast.hpp b/12/ast.hpp index a380ccc..29de43e 100644 --- a/12/ast.hpp +++ b/12/ast.hpp @@ -16,9 +16,8 @@ struct ast { virtual ~ast() = default; virtual void print(int indent, std::ostream& to) const = 0; - virtual void find_free(type_mgr& mgr, - type_env_ptr& env, std::set& into) = 0; - virtual type_ptr typecheck(type_mgr& mgr) = 0; + virtual void find_free(std::set& into) = 0; + virtual type_ptr typecheck(type_mgr& mgr, type_env_ptr& env) = 0; virtual void translate(global_scope& scope) = 0; virtual void compile(const env_ptr& env, std::vector& into) const = 0; @@ -30,7 +29,7 @@ struct pattern { virtual ~pattern() = default; 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& into) 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) {} void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); + void find_free(std::set& into); + type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; @@ -66,8 +65,8 @@ struct ast_lid : public ast { : id(std::move(i)) {} void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); + void find_free(std::set& into); + type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; @@ -79,8 +78,8 @@ struct ast_uid : public ast { : id(std::move(i)) {} void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); + void find_free(std::set& into); + type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; @@ -94,8 +93,8 @@ struct ast_binop : public ast { : op(o), left(std::move(l)), right(std::move(r)) {} void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); + void find_free(std::set& into); + type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; @@ -108,8 +107,8 @@ struct ast_app : public ast { : left(std::move(l)), right(std::move(r)) {} void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); + void find_free(std::set& into); + type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; @@ -123,8 +122,8 @@ struct ast_case : public ast { : of(std::move(o)), branches(std::move(b)) {} void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); + void find_free(std::set& into); + type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; @@ -141,8 +140,8 @@ struct ast_let : public ast { : definitions(std::move(g)), in(std::move(i)) {} void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); + void find_free(std::set& into); + type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; @@ -154,7 +153,7 @@ struct pattern_var : public pattern { : var(std::move(v)) {} void print(std::ostream &to) const; - void insert_bindings(type_mgr& mgr, type_env_ptr& env) const; + void find_variables(std::set& into) 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)) {} void print(std::ostream &to) const; - virtual void insert_bindings(type_mgr& mgr, type_env_ptr& env) const; + void find_variables(std::set& into) const; virtual void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const; }; diff --git a/12/definition.cpp b/12/definition.cpp index a6b636b..60ac44a 100644 --- a/12/definition.cpp +++ b/12/definition.cpp @@ -10,9 +10,15 @@ #include #include -void definition_defn::find_free(type_mgr& mgr, type_env_ptr& env) { - this->env = env; +void definition_defn::find_free() { + 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); return_type = mgr.new_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)); 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); } 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); } -global_definition_ptr& definition_defn::into_global(global_scope& scope) { +global_function& definition_defn::into_global(global_scope& scope) { std::vector all_params; for(auto& free : free_variables) { if(env->is_global(free)) continue; all_params.push_back(free); } all_params.insert(all_params.end(), params.begin(), params.end()); - translate(body, scope); - return scope.add_definition(name, std::move(all_params), std::move(body)); + body->translate(scope); + return scope.add_function(name, std::move(all_params), std::move(body)); } 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) { - auto new_function = - ctx.create_custom_function(constructor->name, constructor->types.size()); - std::vector instructions; - 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(); + global_constructor& c = scope.add_constructor( + constructor->name, constructor->tag, constructor->types.size()); + env->set_mangled_name(constructor->name, c.name); } } -void definition_group::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = type_scope(env); - +void definition_group::find_free(std::set& into) { 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) { if(defs_defn.find(free_var) == defs_defn.end()) { into.insert(free_var); @@ -114,9 +104,11 @@ void definition_group::find_free(type_mgr& mgr, type_env_ptr& env, std::setenv = type_scope(env); + 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) { def_data.second->insert_constructors(); @@ -125,7 +117,7 @@ void definition_group::typecheck(type_mgr& mgr) { function_graph dependency_graph; 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); for(auto& dependency : def_defn.second->nearby_variables) { @@ -140,14 +132,14 @@ void definition_group::typecheck(type_mgr& mgr) { auto& group = *it; for(auto& def_defnn_name : group->members) { 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) { auto& def_defn = defs_defn.find(def_defnn_name)->second; def_defn->typecheck(mgr); } for(auto& def_defnn_name : group->members) { - env->generalize(def_defnn_name, mgr); + this->env->generalize(def_defnn_name, mgr); } } } diff --git a/12/definition.hpp b/12/definition.hpp index 9e15cda..44828d3 100644 --- a/12/definition.hpp +++ b/12/definition.hpp @@ -40,11 +40,11 @@ struct definition_defn { } - void find_free(type_mgr& mgr, type_env_ptr& env); - void insert_types(type_mgr& mgr, visibility v); + void find_free(); + void insert_types(type_mgr& mgr, type_env_ptr& env, visibility v); 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; @@ -64,7 +64,8 @@ struct definition_data { void insert_types(type_env_ptr& env); void insert_constructors() const; - void generate_llvm(llvm_context& ctx); + + void into_globals(global_scope& scope); }; using definition_data_ptr = std::unique_ptr; @@ -77,6 +78,6 @@ struct definition_group { definition_group(visibility v = visibility::local) : vis(v) {} - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - void typecheck(type_mgr& mgr); + void find_free(std::set& into); + void typecheck(type_mgr& mgr, type_env_ptr& env); }; diff --git a/12/global_scope.cpp b/12/global_scope.cpp index b0ae9c0..2107703 100644 --- a/12/global_scope.cpp +++ b/12/global_scope.cpp @@ -1,7 +1,7 @@ #include "global_scope.hpp" #include "ast.hpp" -void global_definition::compile() { +void global_function::compile() { env_ptr new_env = env_ptr(new env_offset(0, nullptr)); for(auto it = params.rbegin(); it != params.rend(); it++) { 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()))); } -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()); } -void global_definition::generate_llvm(llvm_context& ctx) { +void global_function::generate_llvm(llvm_context& ctx) { ctx.builder.SetInsertPoint(&generated_function->getEntryBlock()); for(auto& instruction : instructions) { instruction->gen_llvm(ctx, generated_function); @@ -23,7 +23,50 @@ void global_definition::generate_llvm(llvm_context& ctx) { ctx.builder.CreateRetVoid(); } -global_definition_ptr& global_scope::add_definition(std::string n, std::vector ps, ast_ptr b) { +void global_constructor::generate_llvm(llvm_context& ctx) { + auto new_function = + ctx.create_custom_function(name, arity); + std::vector 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 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); int occurence = 0; if(occurence_it != occurence_count.end()) { @@ -36,8 +79,5 @@ global_definition_ptr& global_scope::add_definition(std::string n, std::vector; struct global_definition { + virtual void generate_llvm(llvm_context& ctx) = 0; +}; + +struct global_function : global_definition { std::string name; std::vector params; ast_ptr body; @@ -16,7 +20,7 @@ struct global_definition { std::vector instructions; llvm::Function* generated_function; - global_definition(std::string n, std::vector ps, ast_ptr b) + global_function(std::string n, std::vector ps, ast_ptr b) : name(std::move(n)), params(std::move(ps)), body(std::move(b)) {} void compile(); @@ -24,11 +28,32 @@ struct global_definition { void generate_llvm(llvm_context& ctx); }; -using global_definition_ptr = std::unique_ptr; +using global_function_ptr = std::unique_ptr; + +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; struct global_scope { std::map occurence_count; - std::vector definitions; + std::vector functions; + std::vector constructors; - global_definition_ptr& add_definition(std::string n, std::vector ps, ast_ptr b); + global_function& add_function(std::string n, std::vector 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); }; diff --git a/12/main.cpp b/12/main.cpp index c7d7234..238f075 100644 --- a/12/main.cpp +++ b/12/main.cpp @@ -39,8 +39,8 @@ void typecheck_program( env->bind("/", binop_type, visibility::global); std::set free; - defs.find_free(mgr, env, free); - defs.typecheck(mgr); + defs.find_free(free); + defs.typecheck(mgr, env); for(auto& pair : defs.env->names) { std::cout << pair.first << ": "; @@ -49,15 +49,16 @@ void typecheck_program( } } -void compile_program(const std::map& defs_defn) { - for(auto& def_defn : defs_defn) { - def_defn.second->compile(); - - for(auto& instruction : def_defn.second->instructions) { - instruction->print(0, std::cout); - } - std::cout << std::endl; +global_scope translate_program(definition_group& group) { + global_scope scope; + for(auto& data : group.defs_data) { + data.second->into_globals(scope); } + 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) { @@ -117,24 +118,14 @@ void output_llvm(llvm_context& ctx, const std::string& filename) { } } -void gen_llvm( - const std::map& defs_data, - const std::map& defs_defn) { +void gen_llvm(global_scope& scope) { llvm_context ctx; gen_llvm_internal_op(ctx, PLUS); gen_llvm_internal_op(ctx, MINUS); gen_llvm_internal_op(ctx, TIMES); gen_llvm_internal_op(ctx, DIVIDE); - for(auto& def_data : defs_data) { - 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); - } + scope.generate_llvm(ctx); ctx.module.print(llvm::outs(), nullptr); output_llvm(ctx, "program.o"); @@ -155,8 +146,9 @@ int main() { } try { typecheck_program(global_defs, mgr, env); - compile_program(global_defs.defs_defn); - gen_llvm(global_defs.defs_data, global_defs.defs_defn); + global_scope scope = translate_program(global_defs); + scope.compile(); + gen_llvm(scope); } catch(unification_error& err) { std::cout << "failed to unify types: " << std::endl; std::cout << " (1) \033[34m"; diff --git a/12/parser.y b/12/parser.y index 883879c..deb0d39 100644 --- a/12/parser.y +++ b/12/parser.y @@ -7,7 +7,7 @@ #include "parser.hpp" #include "parsed_type.hpp" -definition_group global_defs(visibility::global); +definition_group global_defs; extern yy::parser::symbol_type yylex(); @@ -56,7 +56,7 @@ extern yy::parser::symbol_type yylex(); %% program - : definitions { global_defs = std::move($1); } + : definitions { global_defs = std::move($1); global_defs.vis = visibility::global; } ; definitions diff --git a/12/type_env.cpp b/12/type_env.cpp index 65cafbf..048eb82 100644 --- a/12/type_env.cpp +++ b/12/type_env.cpp @@ -31,6 +31,19 @@ bool type_env::is_global(const std::string& name) const { 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 { auto it = type_names.find(name); 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) { 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) { - 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) { diff --git a/12/type_env.hpp b/12/type_env.hpp index a55885d..271a599 100644 --- a/12/type_env.hpp +++ b/12/type_env.hpp @@ -13,11 +13,12 @@ struct type_env { struct variable_data { type_scheme_ptr type; visibility vis; + std::string mangled_name; variable_data() - : variable_data(nullptr, visibility::local) {} - variable_data(type_scheme_ptr t, visibility v) - : type(std::move(t)), vis(v) {} + : variable_data(nullptr, visibility::local, "") {} + variable_data(type_scheme_ptr t, visibility v, std::string n) + : type(std::move(t)), vis(v), mangled_name(std::move(n)) {} }; type_env_ptr parent; @@ -32,6 +33,8 @@ struct type_env { std::set& into) const; type_scheme_ptr lookup(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; void bind(const std::string& name, type_ptr t, visibility v = visibility::local);