From 156aa224ee547a80b6fe92cecdbba1822f9a4608 Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Mon, 25 May 2026 15:34:05 +0200 Subject: [PATCH] Use arena in parser Signed-off-by: CHatingPython --- CMakeLists.txt | 2 ++ furc/include/furc/ast/declaration.hpp | 17 +++++++++++++++++ furc/include/furc/ast/statement.hpp | 6 +++--- furc/include/furc/front/parser.hpp | 5 ++++- furc/include/furc/handle.hpp | 5 +++++ furc/src/front/parser.cpp | 15 +++++++++------ furlang/include/furlang/arena.hpp | 25 ++++++++++++++++++++++--- 7 files changed, 62 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 42362d9..00f2199 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.14) project(furlang VERSION 0.0.0 LANGUAGES CXX) +enable_testing() + find_package(GTest REQUIRED) add_subdirectory(furlang) diff --git a/furc/include/furc/ast/declaration.hpp b/furc/include/furc/ast/declaration.hpp index fee99f8..1f4b780 100644 --- a/furc/include/furc/ast/declaration.hpp +++ b/furc/include/furc/ast/declaration.hpp @@ -62,6 +62,23 @@ class function_definition_node : public function_declarartion_node { public: function_definition_node(front::token name, function_body_handle&& body) : function_declarartion_node(name), m_body(std::move(body)) {} + + ~function_definition_node() override = default; + + function_definition_node(function_definition_node&& other) noexcept + : function_declarartion_node(std::move(other)), m_name(other.m_name), m_body(std::move(other.m_body)) {} + + function_definition_node(const function_definition_node&) = delete; + + function_definition_node& operator=(function_definition_node&& other) noexcept { + if (this == &other) return *this; + function_declarartion_node::operator=(std::move(other)); + m_name = other.m_name; + m_body = std::move(other.m_body); + return *this; + } + + function_definition_node& operator=(const function_definition_node&) = delete; public: declaration_node_t type() const override { return declaration_node_t::FunctionDefinition; } diff --git a/furc/include/furc/ast/statement.hpp b/furc/include/furc/ast/statement.hpp index 806e1f0..3674b11 100644 --- a/furc/include/furc/ast/statement.hpp +++ b/furc/include/furc/ast/statement.hpp @@ -35,14 +35,14 @@ public: class declaration_node; class declaration_statement_node : public statement_node { public: - declaration_statement_node(declaration_node* declaration) - : m_declaration(declaration) {} + declaration_statement_node(node_handle&& declaration) + : m_declaration(std::move(declaration)) {} public: statement_node_t type() const override { return statement_node_t::Declaration; } std::ostream& print(std::ostream& os) const override { return os; } private: - declaration_node* m_declaration = nullptr; + node_handle m_declaration; }; class return_statement_node : public statement_node { diff --git a/furc/include/furc/front/parser.hpp b/furc/include/furc/front/parser.hpp index e0e75e4..59f1971 100644 --- a/furc/include/furc/front/parser.hpp +++ b/furc/include/furc/front/parser.hpp @@ -5,6 +5,7 @@ #include "furc/ast/node.hpp" #include "furc/ast/program.hpp" #include "furc/front/lexer.hpp" +#include "furlang/arena.hpp" #include @@ -22,7 +23,8 @@ public: parser& operator=(parser&&) = default; parser& operator=(const parser&) = delete; public: - ast::node_handle parse(); + // parser owns the arena :3c + ast::node_handle parse() &; private: ast::node_handle parse_declaration(); ast::node_handle parse_statement(); @@ -36,6 +38,7 @@ private: std::string m_filename; std::string m_content; lexer m_lexer; + furlang::arena m_arena; std::vector> m_peekBuffer; }; diff --git a/furc/include/furc/handle.hpp b/furc/include/furc/handle.hpp index 2b9009c..9a87e1a 100644 --- a/furc/include/furc/handle.hpp +++ b/furc/include/furc/handle.hpp @@ -2,6 +2,7 @@ #define FURC_HANDLE_HPP #include "furc/diag.hpp" +#include "furlang/arena.hpp" #include #include @@ -123,6 +124,10 @@ public: handle(location location, Args&&... args) : m_location(location), m_value(std::make_shared(std::forward(args)...)) {} + template >> + handle(location location, furlang::arena& arena, Args&&... args) + : m_location(location), m_value(arena.allocate_shared(std::forward(args)...)) {} + handle(location location, Error&& error) : m_location(location), m_error(std::move(error)) {} diff --git a/furc/src/front/parser.cpp b/furc/src/front/parser.cpp index b71ee0b..e019088 100644 --- a/furc/src/front/parser.cpp +++ b/furc/src/front/parser.cpp @@ -25,8 +25,8 @@ parser::parser(std::string_view filename) m_lexer = { filename, m_content }; } -ast::node_handle parser::parse() { - auto program = std::make_shared(); +ast::node_handle parser::parse() & { + auto program = m_arena.allocate_shared(); while (!m_lexer.empty()) { program->push(std::move(parse_declaration())); @@ -55,11 +55,14 @@ ast::node_handle parser::parse_declaration() { case token_t::Lbrace: { ast::function_body_handle body = parse_body(); if (body.error()) return body; - return ast::node_handle{ first.location(), name, std::move(body) }; + return ast::node_handle{ first.location(), + m_arena, + name, + std::move(body) }; } case token_t::Semicolon: { m_peekBuffer.clear(); - return ast::node_handle{ first.location(), name }; + return ast::node_handle{ first.location(), m_arena, name }; } case token_t::None: case token_t::Identifier: @@ -106,7 +109,7 @@ ast::node_handle parser::parse_statement() { auto err = eat_token(token_t::Semicolon); if (err.error()) return err; - return ast::node_handle{ tok.location() }; + return ast::node_handle{ tok.location(), m_arena }; } default: break; } @@ -114,7 +117,7 @@ ast::node_handle parser::parse_statement() { auto declaration = parse_declaration(); if (declaration.error()) return { declaration.location(), "unexpected token "s + tok->type + ", expected statement" }; - return ast::node_handle{ declaration.location(), declaration }; + return ast::node_handle{ declaration.location(), m_arena, std::move(declaration) }; } ast::function_body_handle parser::parse_body() { diff --git a/furlang/include/furlang/arena.hpp b/furlang/include/furlang/arena.hpp index 857146c..a0111ee 100644 --- a/furlang/include/furlang/arena.hpp +++ b/furlang/include/furlang/arena.hpp @@ -3,6 +3,8 @@ #include #include +#include +#include namespace furlang { @@ -29,9 +31,26 @@ public: arena& operator=(arena&& other) noexcept; arena& operator=(const arena&) = delete; public: - template - T* allocate(std::size_t count = 1) { - return reinterpret_cast(allocate(sizeof(T), count)); + template >> + T* allocate(std::size_t count) { + T* allocated = reinterpret_cast(allocate(sizeof(T), count)); + for (std::size_t i = 0; i < count; ++i) { + new (&allocated[i]) T(); + } + return allocated; + } + + template >> + T* allocate(Args&&... args) { + T* allocated = reinterpret_cast(allocate(sizeof(T), 1)); + new (allocated) T(std::forward(args)...); + return allocated; + } + + template + std::shared_ptr allocate_shared(Args&&... args) { + T* allocated = allocate(std::forward(args)...); + return std::shared_ptr(allocated, [](T* object) { object->~T(); }); } void reset();