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.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #include "definition.hpp"
  2. #include "error.hpp"
  3. #include "ast.hpp"
  4. #include "instruction.hpp"
  5. #include "llvm_context.hpp"
  6. #include <llvm/IR/DerivedTypes.h>
  7. #include <llvm/IR/Function.h>
  8. #include <llvm/IR/Type.h>
  9. void definition_defn::typecheck_first(type_mgr& mgr, type_env& env) {
  10. return_type = mgr.new_type();
  11. type_ptr full_type = return_type;
  12. for(auto it = params.rbegin(); it != params.rend(); it++) {
  13. type_ptr param_type = mgr.new_type();
  14. full_type = type_ptr(new type_arr(param_type, full_type));
  15. param_types.push_back(param_type);
  16. }
  17. env.bind(name, full_type);
  18. }
  19. void definition_defn::typecheck_second(type_mgr& mgr, const type_env& env) const {
  20. type_env new_env = env.scope();
  21. auto param_it = params.begin();
  22. auto type_it = param_types.rbegin();
  23. while(param_it != params.end() && type_it != param_types.rend()) {
  24. new_env.bind(*param_it, *type_it);
  25. param_it++;
  26. type_it++;
  27. }
  28. type_ptr body_type = body->typecheck_common(mgr, new_env);
  29. mgr.unify(return_type, body_type);
  30. }
  31. void definition_defn::resolve(const type_mgr& mgr) {
  32. type_var* var;
  33. body->resolve_common(mgr);
  34. return_type = mgr.resolve(return_type, var);
  35. if(var) throw type_error("ambiguously typed program");
  36. for(auto& param_type : param_types) {
  37. param_type = mgr.resolve(param_type, var);
  38. if(var) throw type_error("ambiguously typed program");
  39. }
  40. }
  41. void definition_defn::compile() {
  42. env_ptr new_env = env_ptr(new env_offset(0, nullptr));
  43. for(auto it = params.rbegin(); it != params.rend(); it++) {
  44. new_env = env_ptr(new env_var(*it, new_env));
  45. }
  46. body->compile(new_env, instructions);
  47. instructions.push_back(instruction_ptr(new instruction_update(params.size())));
  48. instructions.push_back(instruction_ptr(new instruction_pop(params.size())));
  49. }
  50. void definition_defn::gen_llvm_first(llvm_context& ctx) {
  51. generated_function = ctx.create_custom_function(name, params.size());
  52. }
  53. void definition_defn::gen_llvm_second(llvm_context& ctx) {
  54. ctx.builder.SetInsertPoint(&generated_function->getEntryBlock());
  55. for(auto& instruction : instructions) {
  56. instruction->gen_llvm(ctx, generated_function);
  57. }
  58. ctx.builder.CreateRetVoid();
  59. }
  60. void definition_data::typecheck_first(type_mgr& mgr, type_env& env) {
  61. type_data* this_type = new type_data(name);
  62. type_ptr return_type = type_ptr(this_type);
  63. int next_tag = 0;
  64. for(auto& constructor : constructors) {
  65. constructor->tag = next_tag;
  66. this_type->constructors[constructor->name] = { next_tag++ };
  67. type_ptr full_type = return_type;
  68. for(auto it = constructor->types.rbegin(); it != constructor->types.rend(); it++) {
  69. type_ptr type = type_ptr(new type_base(*it));
  70. full_type = type_ptr(new type_arr(type, full_type));
  71. }
  72. env.bind(constructor->name, full_type);
  73. }
  74. }
  75. void definition_data::typecheck_second(type_mgr& mgr, const type_env& env) const {
  76. // Nothing
  77. }
  78. void definition_data::resolve(const type_mgr& mgr) {
  79. // Nothing
  80. }
  81. void definition_data::compile() {
  82. }
  83. void definition_data::gen_llvm_first(llvm_context& ctx) {
  84. for(auto& constructor : constructors) {
  85. auto new_function =
  86. ctx.create_custom_function(constructor->name, constructor->types.size());
  87. std::vector<instruction_ptr> instructions;
  88. instructions.push_back(instruction_ptr(
  89. new instruction_pack(constructor->tag, constructor->types.size())
  90. ));
  91. instructions.push_back(instruction_ptr(new instruction_update(0)));
  92. ctx.builder.SetInsertPoint(&new_function->getEntryBlock());
  93. for (auto& instruction : instructions) {
  94. instruction->gen_llvm(ctx, new_function);
  95. }
  96. ctx.builder.CreateRetVoid();
  97. }
  98. }
  99. void definition_data::gen_llvm_second(llvm_context& ctx) {
  100. // Nothing
  101. }