lily/src/gmachine.hpp

156 lines
4.3 KiB
C++

#pragma once
#include <string>
#include <vector>
#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<instruction*> true_branch;
std::vector<instruction*> 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<std::vector<instruction*>> instructions;
std::map<int, int> const_instructions;
std::ostream& to_stream(std::ostream& os);
void gen_llvm(llvm_context& ctx);
};
class instruction_manager {
private:
std::vector<std::unique_ptr<instruction>> instructions;
public:
template <typename T, typename ... Ts>
T* add_instruction(Ts ... ts) {
auto new_inst = std::unique_ptr<T>(new T(ts...));
T* raw = new_inst.get();
instructions.push_back(std::move(new_inst));
return raw;
}
};
}