diff --git a/CMakeLists.txt b/CMakeLists.txt index 431de19..9d0e055 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,6 @@ project(pl VERSION 0.0.1 LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 23) set(SOURCES - src/ir.cpp src/main.cpp ) diff --git a/include/codegen/fasm_stack.hpp b/include/codegen/fasm_stack.hpp index ee25f4a..7f93e47 100644 --- a/include/codegen/fasm_stack.hpp +++ b/include/codegen/fasm_stack.hpp @@ -68,7 +68,7 @@ private: auto param_slot = m_allocator->Allocate(fn->params().data[0]); appendf("mov %s, rdi\n", GetSlotAddr(param_slot).c_str()); } - for(auto &fOp : fn->ops()) + for(auto &fOp : fn->body().ops()) { GenerateOp(fOp); } diff --git a/include/ir/block.hpp b/include/ir/block.hpp new file mode 100644 index 0000000..a4c5619 --- /dev/null +++ b/include/ir/block.hpp @@ -0,0 +1,35 @@ +#pragma once +#include "ir/op.hpp" + +namespace IR +{ + +using OpView = View; + +using BlockID = unsigned int; + +class Block +{ +public: + Block(BlockID id, OpView&& ops) + : m_id(id), m_ops(ops) {} +public: + const OpView& ops() const { return m_ops; } +public: + StringView Format(int indent) const + { + StringBuilder sb; + sb.AppendIndent(indent); + sb.AppendFormat("b%d:\n", m_id); + for (size_t i = 0; i < m_ops.size; ++i) + { + sb << m_ops.data[i]->Format(indent + 2) << '\n'; + } + return sb.view(); + } +private: + BlockID m_id; + OpView m_ops; +}; + +} // namespace IR diff --git a/include/ir/ir.hpp b/include/ir/ir.hpp index 9ea3306..60f2ac0 100644 --- a/include/ir/ir.hpp +++ b/include/ir/ir.hpp @@ -5,240 +5,29 @@ #include "ir/slot.hpp" #include "ir/allocator.hpp" #include "ir/value.hpp" +#include "ir/ops.hpp" namespace IR { -enum class OpType -{ - EXTERN = 0, - FN, - LOAD_CONST, - LOAD, - STORE, - ADD, - CALL, - COUNT_OPS, -}; - -#define OP_TYPE(x) \ - OpType GetType() const override { return OpType::x; } - -class Op -{ -public: - virtual OpType GetType() const = 0; - virtual ~Op() {} - - virtual StringView Format(int indent) const = 0; -}; - -using OpView = View; -using OpBuilder = Builder; - -class Valued -{ -public: - Valued(Value dest) - : m_dest(dest) {} - ~Valued() = default; -public: - Value result() const { return m_dest; } -private: - Value m_dest; -}; - -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; -}; - -class FnOp : public Op -{ -public: - FnOp(StringView name, const CompoundNode* body, const View& params); - ~FnOp() {} - - OP_TYPE(FN) -public: - StringView Format(int indent) const override - { - StringBuilder sb; - sb.AppendIndent(indent); - sb << "LABEL " << m_name.c_str() << ':' << '\n'; - for (size_t i = 0; i < m_ops.size; ++i) - { - sb << m_ops.data[i]->Format(indent + 2) << '\n'; - } - return sb.view(); - } -public: - const StringView& name() const { return m_name; } - const OpView& ops() const { return m_ops; } - const View& params() const { return m_params; } -private: - StringView m_name; - OpView m_ops; - ValueView m_slots; - View m_params; -}; - -class LoadConstOp : public Op, public Valued -{ -public: - LoadConstOp(Value dest, long value) - : Valued(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 Op, public Valued -{ -public: - LoadOp(Value dest, StringView addr) - : Valued(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 Op, public Valued -{ -public: - AddOp(Value dest, Value lhs, Value rhs) - : Valued(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 Op, public Valued -{ -public: - CallOp(Value dest, StringView callee, ValueView args) - : Valued(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; -}; - class IRBuilder { public: IRBuilder(const Node* root) - : m_root(root) {} + : m_root(root), m_ops(new OpBuilder()) {} public: // TODO: support other literals Value ParseIntLiteral(const IntLiteralNode* literal) { auto dst = AllocateRegister(); - m_ops.Push(new LoadConstOp(dst, literal->integer())); + m_ops->Push(new LoadConstOp(dst, literal->integer())); return dst; } Value ParseVariable(const VariableNode* var) { // auto dst = AllocateRegister(); - // m_ops.Push(new LoadOp(dst, var->name())); + // m_ops->Push(new LoadOp(dst, var->name())); if (m_locals.find(var->name()) == m_locals.end()) { // TODO: throw proper error @@ -257,7 +46,7 @@ public: argRegs.Push(arg); } auto dst = AllocateRegister(); - m_ops.Push(new CallOp(dst, fn->name(), argRegs.view())); + m_ops->Push(new CallOp(dst, fn->name(), argRegs.view())); return dst; } @@ -287,7 +76,7 @@ public: assert(4 == static_cast(ExpressionNode::Operator::COUNT_OPERATORS) && "some operators may not be handled"); switch (expr->op()) { - case ExpressionNode::Operator::Plus: m_ops.Push(new AddOp(dst, lhs, rhs)); break; + case ExpressionNode::Operator::Plus: m_ops->Push(new AddOp(dst, lhs, rhs)); break; default: assert(0 && "TODO: implement other operations"); break; } @@ -300,12 +89,13 @@ public: void ParseVarDecl(const VarDeclNode* varDecl) { auto value = ParseExpression(varDecl->value()); - // m_ops.Push(new StoreOp(varDecl->name(), value)); + // m_ops->Push(new StoreOp(varDecl->name(), value)); m_locals.insert(std::make_pair(varDecl->name(), value)); } - void ParseBlock(const CompoundNode* compound) + Block ParseBlock(const CompoundNode* compound) { + StartBlock(); for (auto &statement : *compound) { switch(statement->GetType()) @@ -314,6 +104,10 @@ public: default: ParseExpression(statement); continue; } } + auto ops = EndBlock(); + auto block = Block(m_block_counter++, std::move(ops->view())); + operator delete(ops); + return block; } OpView Build() @@ -324,32 +118,50 @@ public: // Externs for (auto &extrn : program->externs()) { - m_ops.Push(new ExternOp(extrn->symbol())); + m_ops->Push(new ExternOp(extrn->symbol())); } // Functions for (auto &fn : program->funcs()) { - m_ops.Push(new FnOp(fn->name(), fn->body(), fn->params())); + auto block = ParseBlock(fn->body()); + m_ops->Push(new FnOp(fn->name(), fn->params(), std::move(block))); } - return OpView(m_ops.data, m_ops.size); + return OpView(m_ops->data, m_ops->size); } public: - // TODO: think about safety (copying m_ops.data before giving) - OpView ops() const { return OpView(m_ops.data, m_ops.size); } + // TODO: think about safety (copying m_ops->data before giving) + OpView ops() const { return OpView(m_ops->data, m_ops->size); } +private: + void StartBlock() + { + m_containers.Push(m_ops); + m_ops = new OpBuilder(); + } + + OpBuilder* EndBlock() + { + assert(m_containers.size > 0 && "containers stack is empty"); + auto current = m_ops; + m_ops = m_containers.data[m_containers.size - 1]; + m_containers.size--; + return current; + } private: Value AllocateRegister() { return Value(m_value_counter++); } private: - OpBuilder m_ops; const Node* m_root = nullptr; + OpBuilder* m_ops = nullptr; unsigned int m_value_counter = 0; - + unsigned int m_block_counter = 0; std::unordered_map m_locals; + + Builder m_containers; }; } // namespace IR diff --git a/include/ir/op.hpp b/include/ir/op.hpp new file mode 100644 index 0000000..fa616d6 --- /dev/null +++ b/include/ir/op.hpp @@ -0,0 +1,50 @@ +#pragma once +#include "prelude/string.hpp" +#include "ir/value.hpp" + +namespace IR +{ + +enum class OpType +{ + EXTERN = 0, + FN, + LOAD_CONST, + LOAD, + STORE, + ADD, + CALL, + COUNT_OPS, +}; + +#define OP_TYPE(x) \ + OpType GetType() const override { return OpType::x; } + +class Op +{ +public: + virtual OpType GetType() const = 0; + virtual bool Valued() const { return false; }; + virtual ~Op() {} + + virtual StringView Format(int indent) const = 0; +}; + +using OpView = View; +using OpBuilder = Builder; + +class OpValued : public Op +{ +public: + OpValued(Value dest) + : m_dest(dest) {} + ~OpValued() = default; +public: + Value result() const { return m_dest; } +protected: + bool Valued() const override { return true; } +private: + Value m_dest; +}; + +} // namespace IR \ No newline at end of file diff --git a/include/ir/ops.hpp b/include/ir/ops.hpp new file mode 100644 index 0000000..3136e6c --- /dev/null +++ b/include/ir/ops.hpp @@ -0,0 +1,183 @@ +#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 diff --git a/include/parser/ast.hpp b/include/parser/ast.hpp index c9db9b3..d08db77 100644 --- a/include/parser/ast.hpp +++ b/include/parser/ast.hpp @@ -3,222 +3,7 @@ #include #include #include "parser/lexer.hpp" - -enum class NodeType -{ - Expression = 0, - // TODO: abstract "Literal" node type - IntLiteral, - Extern, - FnDecl, - FnCall, - Variable, - VarDecl, - Compound, - Program, - COUNT_NODES, -}; - -#define NODE_TYPE(x) \ - NodeType GetType() const override { return NodeType::x; } - -class Node -{ -public: - virtual NodeType GetType() const = 0; - virtual ~Node() {} -}; - -class ExpressionNode : public Node -{ -public: - enum class Operator - { - Plus = 0, - Minus, - Divide, - Multiply, - COUNT_OPERATORS, - }; -public: - ExpressionNode(Node* left, Node* right, Operator op) - : m_left(left), m_right(right), m_op(op) {} - ~ExpressionNode() override { - delete m_left; - delete m_right; - } - - NODE_TYPE(Expression) -public: - Node* left() const { return m_left; } - Node* right() const { return m_right; } - Operator op() const { return m_op; } -private: - Node* m_left; - Node* m_right; - Operator m_op; -}; - -// TODO: Maybe just LiteralNode with double or int literals support -class IntLiteralNode : public Node -{ -public: - IntLiteralNode(long value) - : m_int_value(value) {} - ~IntLiteralNode() override {} - - NODE_TYPE(IntLiteral) -public: - long integer() const { return m_int_value; } -private: - long m_int_value; -}; - -class ExternNode : public Node -{ -public: - // TODO: support multiple extern symbols - ExternNode(StringView symbol) - : m_symbol(symbol) {} - ~ExternNode() override = default; - - NODE_TYPE(Extern) -public: - const StringView& symbol() const { return m_symbol; } -private: - StringView m_symbol; -}; - -class CompoundNode : public Node -{ -public: - CompoundNode() = default; - - NODE_TYPE(Compound) - - // --- Iteration --- - auto begin() { return m_nodes.begin(); } - auto end() { return m_nodes.end(); } - auto begin() const { return m_nodes.begin(); } - auto end() const { return m_nodes.end(); } - - // --- Access by index --- - Node* operator[](size_t i) { return m_nodes[i]; } - const Node* operator[](size_t i) const { return m_nodes[i]; } - - Node* at(size_t i) { return m_nodes.at(i); } - const Node* at(size_t i) const { return m_nodes.at(i); } - - // --- Modifiers --- - void addNode(Node* n) { m_nodes.push_back(n); } - void removeNode(size_t idx) { m_nodes.erase(m_nodes.begin() + idx); } - - // If you want full expose for iteration but not modification - const std::vector& nodes() const { return m_nodes; } - - size_t size() const { return m_nodes.size(); } - bool empty() const { return m_nodes.empty(); } -private: - std::vector m_nodes; -}; - -class FnDeclNode : public Node -{ -public: - // TODO: support parameters - FnDeclNode(const StringView& name, CompoundNode* body, View params) - : m_name(name), m_body(body), m_params(params) {} - ~FnDeclNode() override { - delete m_body; - } - - NODE_TYPE(FnDecl) -public: - const StringView& name() const { return m_name; } - const CompoundNode* body() const { return m_body; } - const View& params() const { return m_params; } -private: - StringView m_name; - CompoundNode* m_body; - View m_params; -}; - -class FnCallNode : public Node -{ -public: - // TODO: support multiple arguments - FnCallNode(const StringView& name, Node* arg) - : m_name(name), m_arg(arg) {} - ~FnCallNode() override { - delete m_arg; - } - - NODE_TYPE(FnCall) -public: - const StringView& name() const { return m_name; } - // TODO: support multiple args - const Node* arg() const { return m_arg; } -private: - StringView m_name; - Node* m_arg; -}; - -class VariableNode : public Node -{ -public: - VariableNode(const StringView& name) - : m_name(name) {} - ~VariableNode() override = default; - - NODE_TYPE(Variable) -public: - const StringView& name() const { return m_name; } -private: - StringView m_name; -}; - -class VarDeclNode : public Node -{ -public: - VarDeclNode(const StringView& name, Node* value) - : m_name(name), m_value(value) {} - ~VarDeclNode() override { - delete m_value; - } - - NODE_TYPE(VarDecl) -public: - const StringView& name() const { return m_name; } - const Node* value() const { return m_value; } -private: - StringView m_name; - Node* m_value; -}; - -class ProgramNode : public Node -{ -public: - ProgramNode() = default; - - NODE_TYPE(Program) -public: - void PushFunction(FnDeclNode* fn) - { - m_funcs.push_back(fn); - } - - void PushExtern(ExternNode* extrn) - { - m_externs.push_back(extrn); - } -public: - const std::vector externs() const { return m_externs; } - const std::vector funcs() const { return m_funcs; } -private: - std::vector m_funcs; - std::vector m_externs; -}; - +#include "parser/nodes.hpp" class AstParser { diff --git a/include/parser/nodes.hpp b/include/parser/nodes.hpp new file mode 100644 index 0000000..88839f9 --- /dev/null +++ b/include/parser/nodes.hpp @@ -0,0 +1,217 @@ +#pragma once +#include "prelude/string.hpp" + +enum class NodeType +{ + Expression = 0, + // TODO: abstract "Literal" node type + IntLiteral, + Extern, + FnDecl, + FnCall, + Variable, + VarDecl, + Compound, + Program, + COUNT_NODES, +}; + +#define NODE_TYPE(x) \ + NodeType GetType() const override { return NodeType::x; } + +class Node +{ +public: + virtual NodeType GetType() const = 0; + virtual ~Node() {} +}; + +class ExpressionNode : public Node +{ +public: + enum class Operator + { + Plus = 0, + Minus, + Divide, + Multiply, + COUNT_OPERATORS, + }; +public: + ExpressionNode(Node* left, Node* right, Operator op) + : m_left(left), m_right(right), m_op(op) {} + ~ExpressionNode() override { + delete m_left; + delete m_right; + } + + NODE_TYPE(Expression) +public: + Node* left() const { return m_left; } + Node* right() const { return m_right; } + Operator op() const { return m_op; } +private: + Node* m_left; + Node* m_right; + Operator m_op; +}; + +// TODO: Maybe just LiteralNode with double or int literals support +class IntLiteralNode : public Node +{ +public: + IntLiteralNode(long value) + : m_int_value(value) {} + ~IntLiteralNode() override {} + + NODE_TYPE(IntLiteral) +public: + long integer() const { return m_int_value; } +private: + long m_int_value; +}; + +class ExternNode : public Node +{ +public: + // TODO: support multiple extern symbols + ExternNode(StringView symbol) + : m_symbol(symbol) {} + ~ExternNode() override = default; + + NODE_TYPE(Extern) +public: + const StringView& symbol() const { return m_symbol; } +private: + StringView m_symbol; +}; + +class CompoundNode : public Node +{ +public: + CompoundNode() = default; + + NODE_TYPE(Compound) + + // --- Iteration --- + auto begin() { return m_nodes.begin(); } + auto end() { return m_nodes.end(); } + auto begin() const { return m_nodes.begin(); } + auto end() const { return m_nodes.end(); } + + // --- Access by index --- + Node* operator[](size_t i) { return m_nodes[i]; } + const Node* operator[](size_t i) const { return m_nodes[i]; } + + Node* at(size_t i) { return m_nodes.at(i); } + const Node* at(size_t i) const { return m_nodes.at(i); } + + // --- Modifiers --- + void addNode(Node* n) { m_nodes.push_back(n); } + void removeNode(size_t idx) { m_nodes.erase(m_nodes.begin() + idx); } + + // If you want full expose for iteration but not modification + const std::vector& nodes() const { return m_nodes; } + + size_t size() const { return m_nodes.size(); } + bool empty() const { return m_nodes.empty(); } +private: + std::vector m_nodes; +}; + +class FnDeclNode : public Node +{ +public: + // TODO: support parameters + FnDeclNode(const StringView& name, CompoundNode* body, View params) + : m_name(name), m_body(body), m_params(params) {} + ~FnDeclNode() override { + delete m_body; + } + + NODE_TYPE(FnDecl) +public: + const StringView& name() const { return m_name; } + const CompoundNode* body() const { return m_body; } + const View& params() const { return m_params; } +private: + StringView m_name; + CompoundNode* m_body; + View m_params; +}; + +class FnCallNode : public Node +{ +public: + // TODO: support multiple arguments + FnCallNode(const StringView& name, Node* arg) + : m_name(name), m_arg(arg) {} + ~FnCallNode() override { + delete m_arg; + } + + NODE_TYPE(FnCall) +public: + const StringView& name() const { return m_name; } + // TODO: support multiple args + const Node* arg() const { return m_arg; } +private: + StringView m_name; + Node* m_arg; +}; + +class VariableNode : public Node +{ +public: + VariableNode(const StringView& name) + : m_name(name) {} + ~VariableNode() override = default; + + NODE_TYPE(Variable) +public: + const StringView& name() const { return m_name; } +private: + StringView m_name; +}; + +class VarDeclNode : public Node +{ +public: + VarDeclNode(const StringView& name, Node* value) + : m_name(name), m_value(value) {} + ~VarDeclNode() override { + delete m_value; + } + + NODE_TYPE(VarDecl) +public: + const StringView& name() const { return m_name; } + const Node* value() const { return m_value; } +private: + StringView m_name; + Node* m_value; +}; + +class ProgramNode : public Node +{ +public: + ProgramNode() = default; + + NODE_TYPE(Program) +public: + void PushFunction(FnDeclNode* fn) + { + m_funcs.push_back(fn); + } + + void PushExtern(ExternNode* extrn) + { + m_externs.push_back(extrn); + } +public: + const std::vector externs() const { return m_externs; } + const std::vector funcs() const { return m_funcs; } +private: + std::vector m_funcs; + std::vector m_externs; +}; \ No newline at end of file diff --git a/src/ir.cpp b/src/ir.cpp deleted file mode 100644 index c237fb8..0000000 --- a/src/ir.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "ir/ir.hpp" - -IR::FnOp::FnOp(StringView name, const CompoundNode* body, const View& params) - : m_name(name), m_params(params) -{ - IRBuilder ir(body); // Now IRBuilder is complete → OK - ir.ParseBlock(body); - m_ops = std::move(ir.ops()); -} \ No newline at end of file