A Hugo incarnation of the blog.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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. }