diff --git a/code/compiler/12/ast.cpp b/code/compiler/12/ast.cpp index e6d8cbb..862273f 100644 --- a/code/compiler/12/ast.cpp +++ b/code/compiler/12/ast.cpp @@ -3,6 +3,7 @@ #include "binop.hpp" #include "error.hpp" #include "type_env.hpp" +#include "env.hpp" static void print_indent(int n, std::ostream& to) { while(n--) to << " "; @@ -21,6 +22,10 @@ type_ptr ast_int::typecheck(type_mgr& mgr) { return type_ptr(new type_app(env->lookup_type("Int"))); } +void ast_int::translate(global_scope& scope) { + +} + void ast_int::compile(const env_ptr& env, std::vector& into) const { into.push_back(instruction_ptr(new instruction_pushint(value))); } @@ -39,6 +44,10 @@ type_ptr ast_lid::typecheck(type_mgr& mgr) { return env->lookup(id)->instantiate(mgr); } +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) ? @@ -59,6 +68,10 @@ type_ptr ast_uid::typecheck(type_mgr& mgr) { return env->lookup(id)->instantiate(mgr); } +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))); } @@ -90,6 +103,11 @@ type_ptr ast_binop::typecheck(type_mgr& mgr) { return return_type; } +void ast_binop::translate(global_scope& scope) { + left->translate(scope); + right->translate(scope); +} + void ast_binop::compile(const env_ptr& env, std::vector& into) const { right->compile(env, into); left->compile(env_ptr(new env_offset(1, env)), into); @@ -122,6 +140,11 @@ type_ptr ast_app::typecheck(type_mgr& mgr) { return return_type; } +void ast_app::translate(global_scope& scope) { + left->translate(scope); + right->translate(scope); +} + void ast_app::compile(const env_ptr& env, std::vector& into) const { right->compile(env, into); left->compile(env_ptr(new env_offset(1, env)), into); @@ -170,6 +193,13 @@ type_ptr ast_case::typecheck(type_mgr& mgr) { return branch_type; } +void ast_case::translate(global_scope& scope) { + of->translate(scope); + for(auto& branch : branches) { + branch->expr->translate(scope); + } +} + void ast_case::compile(const env_ptr& env, std::vector& into) const { type_app* app_type = dynamic_cast(input_type.get()); type_data* type = dynamic_cast(app_type->constructor.get()); @@ -248,8 +278,36 @@ type_ptr ast_let::typecheck(type_mgr& mgr) { return in->typecheck(mgr); } +void ast_let::translate(global_scope& 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; + + ast_ptr global_app(new ast_lid(global_definition->name)); + for(auto& param : global_definition->params) { + if(!(captured--)) break; + ast_ptr new_arg(new ast_lid(param)); + global_app = ast_ptr(new ast_app(std::move(global_app), std::move(new_arg))); + } + translated_definitions.push_back({ global_definition->name, std::move(global_app) }); + } + in->translate(scope); +} + void ast_let::compile(const env_ptr& env, std::vector& into) const { - throw 0; + into.push_back(instruction_ptr(new instruction_alloc(translated_definitions.size()))); + env_ptr new_env = env; + for(auto& def : translated_definitions) { + new_env = env_ptr(new env_var(def.first, std::move(new_env))); + } + int offset = translated_definitions.size() - 1; + for(auto& def : translated_definitions) { + def.second->compile(new_env, into); + into.push_back(instruction_ptr(new instruction_update(offset--))); + } + in->compile(new_env, into); } void pattern_var::print(std::ostream& to) const { diff --git a/code/compiler/12/ast.hpp b/code/compiler/12/ast.hpp index d3887bd..a380ccc 100644 --- a/code/compiler/12/ast.hpp +++ b/code/compiler/12/ast.hpp @@ -8,6 +8,7 @@ #include "instruction.hpp" #include "env.hpp" #include "definition.hpp" +#include "global_scope.hpp" struct ast { type_env_ptr env; @@ -18,6 +19,7 @@ struct ast { 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 translate(global_scope& scope) = 0; virtual void compile(const env_ptr& env, std::vector& into) const = 0; }; @@ -53,6 +55,7 @@ struct ast_int : public ast { 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 translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; @@ -65,6 +68,7 @@ struct ast_lid : public ast { 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 translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; @@ -77,6 +81,7 @@ struct ast_uid : public ast { 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 translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; @@ -91,6 +96,7 @@ struct ast_binop : public ast { 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 translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; @@ -104,6 +110,7 @@ struct ast_app : public ast { 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 translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; @@ -118,19 +125,25 @@ struct ast_case : public ast { 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 translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; struct ast_let : public ast { + using basic_definition = std::pair; + definition_group definitions; ast_ptr in; + std::vector translated_definitions; + ast_let(definition_group g, ast_ptr i) : 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 translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; diff --git a/code/compiler/12/definition.cpp b/code/compiler/12/definition.cpp index 6d92133..a6b636b 100644 --- a/code/compiler/12/definition.cpp +++ b/code/compiler/12/definition.cpp @@ -35,26 +35,16 @@ void definition_defn::typecheck(type_mgr& mgr) { mgr.unify(return_type, body_type); } -void definition_defn::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)); - } - body->compile(new_env, instructions); - instructions.push_back(instruction_ptr(new instruction_update(params.size()))); - instructions.push_back(instruction_ptr(new instruction_pop(params.size()))); -} -void definition_defn::declare_llvm(llvm_context& ctx) { - generated_function = ctx.create_custom_function(name, params.size()); -} - -void definition_defn::generate_llvm(llvm_context& ctx) { - ctx.builder.SetInsertPoint(&generated_function->getEntryBlock()); - for(auto& instruction : instructions) { - instruction->gen_llvm(ctx, generated_function); +global_definition_ptr& 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); } - ctx.builder.CreateRetVoid(); + 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)); } void definition_data::insert_types(type_env_ptr& env) { diff --git a/code/compiler/12/definition.hpp b/code/compiler/12/definition.hpp index ce86bb3..9e15cda 100644 --- a/code/compiler/12/definition.hpp +++ b/code/compiler/12/definition.hpp @@ -7,6 +7,7 @@ #include "llvm_context.hpp" #include "parsed_type.hpp" #include "type_env.hpp" +#include "global_scope.hpp" struct ast; using ast_ptr = std::unique_ptr; @@ -34,10 +35,6 @@ struct definition_defn { type_ptr full_type; type_ptr return_type; - std::vector instructions; - - llvm::Function* generated_function; - definition_defn(std::string n, std::vector p, ast_ptr b) : name(std::move(n)), params(std::move(p)), body(std::move(b)) { @@ -46,9 +43,8 @@ struct definition_defn { void find_free(type_mgr& mgr, type_env_ptr& env); void insert_types(type_mgr& mgr, visibility v); void typecheck(type_mgr& mgr); - void compile(); - void declare_llvm(llvm_context& ctx); - void generate_llvm(llvm_context& ctx); + + global_definition_ptr& into_global(global_scope& scope); }; using definition_defn_ptr = std::unique_ptr; diff --git a/code/compiler/12/env.hpp b/code/compiler/12/env.hpp index a8fbbec..9d0dfbe 100644 --- a/code/compiler/12/env.hpp +++ b/code/compiler/12/env.hpp @@ -15,7 +15,7 @@ struct env_var : public env { std::string name; env_ptr parent; - env_var(std::string& n, env_ptr p) + env_var(std::string n, env_ptr p) : name(std::move(n)), parent(std::move(p)) {} int get_offset(const std::string& name) const; diff --git a/code/compiler/12/type_env.cpp b/code/compiler/12/type_env.cpp index e0fd33f..65cafbf 100644 --- a/code/compiler/12/type_env.cpp +++ b/code/compiler/12/type_env.cpp @@ -24,6 +24,13 @@ type_scheme_ptr type_env::lookup(const std::string& name) const { return nullptr; } +bool type_env::is_global(const std::string& name) const { + auto it = names.find(name); + if(it != names.end()) return it->second.vis == visibility::global; + if(parent) return parent->is_global(name); + return false; +} + 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; diff --git a/code/compiler/12/type_env.hpp b/code/compiler/12/type_env.hpp index f61a674..a55885d 100644 --- a/code/compiler/12/type_env.hpp +++ b/code/compiler/12/type_env.hpp @@ -31,6 +31,7 @@ struct type_env { void find_free_except(const type_mgr& mgr, const std::string& avoid, std::set& into) const; type_scheme_ptr lookup(const std::string& name) const; + bool is_global(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);