#pragma once #include "prelude/string.hpp" #include "parser/nodes.hpp" #include "ir/value.hpp" #include "ir/op.hpp" #include "ir/block.hpp" namespace IR { class ExternOp : public Op { public: ExternOp(StringView symbol) : m_symbol(symbol) {} ~ExternOp() {} OP_TYPE(EXTERN) public: StringView Format(int indent) const override { StringBuilder sb; sb.AppendIndent(indent); sb << "EXTRN " << m_symbol.c_str(); return sb.view(); } public: const StringView& symbol() const { return m_symbol; } private: StringView m_symbol; }; // TODO: Make function return value (i.e. inhreit the OpValued class instead) class FnOp : public Op { public: FnOp(StringView name, const View& params, Block&& block) : m_name(name), m_params(params), m_body(block) {} ~FnOp() {} OP_TYPE(FN) public: StringView Format(int indent) const override { StringBuilder sb; sb.AppendIndent(indent); sb << "LABEL " << m_name.c_str() << ':' << '\n'; sb << m_body.Format(indent); return sb.view(); } public: const StringView& name() const { return m_name; } const Block& body() const { return m_body; } const View& params() const { return m_params; } private: StringView m_name; ValueView m_slots; View m_params; Block m_body; }; class LoadConstOp : public OpValued { public: LoadConstOp(Value dest, long value) : OpValued(dest), m_value(value) {} ~LoadConstOp() {} OP_TYPE(LOAD_CONST) public: StringView Format(int indent) const override { StringBuilder sb; sb.AppendIndent(indent); sb << result().Format() << " = LOAD_CONST " << m_value; return sb.view(); } public: long value() const { return m_value; } private: long m_value; }; class LoadOp : public OpValued { public: LoadOp(Value dest, StringView addr) : OpValued(dest), m_addr(addr) {} ~LoadOp() {} OP_TYPE(LOAD) public: StringView Format(int indent) const override { StringBuilder sb; sb.AppendIndent(indent); sb << result().Format() << " = LOAD \"" << m_addr.c_str() << "\""; return sb.view(); } public: const StringView& addr() const { return m_addr; } private: StringView m_addr; }; class StoreOp : public Op { public: StoreOp(StringView addr, Value src) : m_addr(addr), m_src(src) {} ~StoreOp() {} OP_TYPE(STORE) public: StringView Format(int indent) const override { StringBuilder sb; sb.AppendIndent(indent); sb << "STORE \"" << m_addr.c_str() << "\", " << m_src.Format(); return sb.view(); } public: const StringView& addr() const { return m_addr; } Value src() const { return m_src; } private: StringView m_addr; Value m_src; }; class AddOp : public OpValued { public: AddOp(Value dest, Value lhs, Value rhs) : OpValued(dest), m_lhs(lhs), m_rhs(rhs) {} ~AddOp() {} OP_TYPE(ADD) public: StringView Format(int indent) const override { StringBuilder sb; sb.AppendIndent(indent); sb << result().Format() << " = ADD " << m_lhs.Format() << ", " << m_rhs.Format(); return sb.view(); } public: Value lhs() const { return m_lhs; } Value rhs() const { return m_rhs; } private: Value m_lhs; Value m_rhs; }; class CallOp : public OpValued { public: CallOp(Value dest, StringView callee, ValueView args) : OpValued(dest), m_callee(callee), m_args(args) {} ~CallOp() {} OP_TYPE(CALL) public: StringView Format(int indent) const override { StringBuilder sb; for (size_t i = 0; i < m_args.size; ++i) { sb.AppendIndent(indent); sb << "PARAM " << m_args.data[i].Format() << '\n'; } sb.AppendIndent(indent); sb << result().Format() << " = CALL " << m_callee.c_str(); return sb.view(); } public: const StringView& callee() const { return m_callee; } const ValueView& args() const { return m_args; } private: StringView m_callee; ValueView m_args; }; } // namespace IR