#pragma once #include #include #include "binop.hpp" #include "llvm.hpp" namespace lily { struct instruction { virtual ~instruction() = default; virtual std::ostream& to_stream(std::ostream& os) = 0; virtual void gen_llvm(llvm_context& ctx) = 0; }; std::ostream& operator<<(std::ostream& os, instruction& inst); struct instruction_slide : instruction { int amount; instruction_slide(int a) : amount(a) {} std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_alloc : instruction { int amount; instruction_alloc(int a) : amount(a) {} std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_pop : instruction { int amount; instruction_pop(int a) : amount(a) {} std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_unwind : instruction { std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_push_global : instruction { std::string name; instruction_push_global(std::string n) : name(std::move(n)) {} std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_push_int : instruction { int value; instruction_push_int(int v) : value(v) {} std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_push_str : instruction { std::string str; instruction_push_str(std::string s) : str(std::move(s)) {} std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_push : instruction { int offset; instruction_push(int o) : offset(o) {} std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_mkapp : instruction { std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_eval : instruction { std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_op : instruction { binop op; instruction_op(binop o) : op(o) {} std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_eq : instruction { std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_cond : instruction { std::vector true_branch; std::vector false_branch; std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_update : instruction { int offset; instruction_update(int o) : offset(o) {} std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_pack : instruction { int constructor; int arity; instruction_pack(int c, int a) : constructor(c), arity(a) {} std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_split : instruction { int arity; instruction_split(int a) : arity(a) {} std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; struct instruction_jump : instruction { std::vector> instructions; std::map const_instructions; std::ostream& to_stream(std::ostream& os); void gen_llvm(llvm_context& ctx); }; class instruction_manager { private: std::vector> instructions; public: template T* add_instruction(Ts ... ts) { auto new_inst = std::unique_ptr(new T(ts...)); T* raw = new_inst.get(); instructions.push_back(std::move(new_inst)); return raw; } }; }