A Hugo incarnation of the blog.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

definition.cpp 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #include "definition.hpp"
  2. #include "error.hpp"
  3. #include "ast.hpp"
  4. #include "instruction.hpp"
  5. #include "llvm_context.hpp"
  6. #include "type.hpp"
  7. #include "type_env.hpp"
  8. #include <llvm/IR/DerivedTypes.h>
  9. #include <llvm/IR/Function.h>
  10. #include <llvm/IR/Type.h>
  11. void definition_defn::find_free(type_mgr& mgr, type_env_ptr& env) {
  12. this->env = env;
  13. var_env = type_scope(env);
  14. return_type = mgr.new_type();
  15. full_type = return_type;
  16. for(auto it = params.rbegin(); it != params.rend(); it++) {
  17. type_ptr param_type = mgr.new_type();
  18. full_type = type_ptr(new type_arr(param_type, full_type));
  19. var_env->bind(*it, param_type);
  20. }
  21. body->find_free(mgr, var_env, free_variables);
  22. }
  23. void definition_defn::insert_types(type_mgr& mgr) {
  24. env->bind(name, full_type);
  25. }
  26. void definition_defn::typecheck(type_mgr& mgr) {
  27. type_ptr body_type = body->typecheck(mgr);
  28. mgr.unify(return_type, body_type);
  29. }
  30. void definition_defn::compile() {
  31. env_ptr new_env = env_ptr(new env_offset(0, nullptr));
  32. for(auto it = params.rbegin(); it != params.rend(); it++) {
  33. new_env = env_ptr(new env_var(*it, new_env));
  34. }
  35. body->compile(new_env, instructions);
  36. instructions.push_back(instruction_ptr(new instruction_update(params.size())));
  37. instructions.push_back(instruction_ptr(new instruction_pop(params.size())));
  38. }
  39. void definition_defn::declare_llvm(llvm_context& ctx) {
  40. generated_function = ctx.create_custom_function(name, params.size());
  41. }
  42. void definition_defn::generate_llvm(llvm_context& ctx) {
  43. ctx.builder.SetInsertPoint(&generated_function->getEntryBlock());
  44. for(auto& instruction : instructions) {
  45. instruction->gen_llvm(ctx, generated_function);
  46. }
  47. ctx.builder.CreateRetVoid();
  48. }
  49. void definition_data::insert_types(type_env_ptr& env) {
  50. this->env = env;
  51. env->bind_type(name, type_ptr(new type_data(name, vars.size())));
  52. }
  53. void definition_data::insert_constructors() const {
  54. type_ptr this_type_ptr = env->lookup_type(name);
  55. type_data* this_type = static_cast<type_data*>(this_type_ptr.get());
  56. int next_tag = 0;
  57. std::set<std::string> var_set;
  58. type_app* return_app = new type_app(std::move(this_type_ptr));
  59. type_ptr return_type(return_app);
  60. for(auto& var : vars) {
  61. if(var_set.find(var) != var_set.end()) throw 0;
  62. var_set.insert(var);
  63. return_app->arguments.push_back(type_ptr(new type_var(var)));
  64. }
  65. for(auto& constructor : constructors) {
  66. constructor->tag = next_tag;
  67. this_type->constructors[constructor->name] = { next_tag++ };
  68. type_ptr full_type = return_type;
  69. for(auto it = constructor->types.rbegin(); it != constructor->types.rend(); it++) {
  70. type_ptr type = (*it)->to_type(var_set, env);
  71. full_type = type_ptr(new type_arr(type, full_type));
  72. }
  73. type_scheme_ptr full_scheme(new type_scheme(std::move(full_type)));
  74. full_scheme->forall.insert(full_scheme->forall.begin(), vars.begin(), vars.end());
  75. env->bind(constructor->name, full_scheme);
  76. }
  77. }
  78. void definition_data::generate_llvm(llvm_context& ctx) {
  79. for(auto& constructor : constructors) {
  80. auto new_function =
  81. ctx.create_custom_function(constructor->name, constructor->types.size());
  82. std::vector<instruction_ptr> instructions;
  83. instructions.push_back(instruction_ptr(
  84. new instruction_pack(constructor->tag, constructor->types.size())
  85. ));
  86. instructions.push_back(instruction_ptr(new instruction_update(0)));
  87. ctx.builder.SetInsertPoint(&new_function->getEntryBlock());
  88. for (auto& instruction : instructions) {
  89. instruction->gen_llvm(ctx, new_function);
  90. }
  91. ctx.builder.CreateRetVoid();
  92. }
  93. }