#pragma once #include #include #include "instruction.hpp" #include "llvm_context.hpp" #include "type_env.hpp" struct ast; using ast_ptr = std::unique_ptr; struct definition { virtual ~definition() = default; virtual void typecheck_first(type_mgr& mgr, type_env& env) = 0; virtual void typecheck_second(type_mgr& mgr, const type_env& env) const = 0; virtual void resolve(const type_mgr& mgr) = 0; virtual void compile() = 0; virtual void gen_llvm_first(llvm_context& ctx) = 0; virtual void gen_llvm_second(llvm_context& ctx) = 0; }; using definition_ptr = std::unique_ptr; struct constructor { std::string name; std::vector types; int8_t tag; constructor(std::string n, std::vector ts) : name(std::move(n)), types(std::move(ts)) {} }; using constructor_ptr = std::unique_ptr; struct definition_defn : public definition { std::string name; std::vector params; ast_ptr body; type_ptr return_type; std::vector param_types; 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)) { } void typecheck_first(type_mgr& mgr, type_env& env); void typecheck_second(type_mgr& mgr, const type_env& env) const; void resolve(const type_mgr& mgr); void compile(); void gen_llvm_first(llvm_context& ctx); void gen_llvm_second(llvm_context& ctx); }; struct definition_data : public definition { std::string name; std::vector constructors; definition_data(std::string n, std::vector cs) : name(std::move(n)), constructors(std::move(cs)) {} void typecheck_first(type_mgr& mgr, type_env& env); void typecheck_second(type_mgr& mgr, const type_env& env) const; void resolve(const type_mgr& mgr); void compile(); void gen_llvm_first(llvm_context& ctx); void gen_llvm_second(llvm_context& ctx); };