A Hugo incarnation of the blog.
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

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