diff --git a/include/artic/arena.h b/include/artic/arena.h new file mode 100644 index 0000000..40e63cd --- /dev/null +++ b/include/artic/arena.h @@ -0,0 +1,62 @@ +#ifndef ARTIC_ARENA_H +#define ARTIC_ARENA_H + +#include +#include +#include + +template +/** works like unique_ptr but doesn't actually own anything */ +struct arena_ptr { + T* _ptr; + + arena_ptr() : _ptr(nullptr) {} + arena_ptr(T* ptr) : _ptr(ptr) {} + + // template, bool> = true> + // arena_ptr(arena_ptr& other) : _ptr(other._ptr) {} + + template, bool> = true> + arena_ptr(arena_ptr&& other) : _ptr(other._ptr) { + other._ptr = nullptr; + } + ~arena_ptr() { + _ptr = nullptr; + } + + // arena_ptr& operator=(const arena_ptr& other) { _ptr = other._ptr; return *this; } + arena_ptr& operator=(arena_ptr&& other) { _ptr = other._ptr; other._ptr = nullptr; return *this; } + + T* operator->() const { return _ptr; } + T& operator*() const { return *_ptr; } + operator bool() const { return _ptr; } + + T* get() const { return _ptr; } + + void swap(arena_ptr& other) { + T* tmp = other._ptr; + other._ptr = _ptr; + _ptr = tmp; + } +}; + +struct Arena { + Arena(); + ~Arena(); + + template + arena_ptr make_ptr(Args&& ...args) { + void* ptr = alloc(sizeof(T)); + new (ptr) T (std::forward(args)...); + return arena_ptr(static_cast(ptr)); + } +private: + void* alloc(size_t); + void grow(); + + size_t _block_size; + size_t _available; + std::vector _data; +}; + +#endif // ARTIC_ARENA_H diff --git a/include/artic/ast.h b/include/artic/ast.h index a7c4aff..2fba011 100644 --- a/include/artic/ast.h +++ b/include/artic/ast.h @@ -5,6 +5,7 @@ #include #include +#include "artic/arena.h" #include "artic/loc.h" #include "artic/log.h" #include "artic/cast.h" @@ -25,12 +26,8 @@ class TypeChecker; class Emitter; class Summoner; -template using Ptr = std::unique_ptr; -template using PtrVector = std::vector>; -template -std::unique_ptr make_ptr(Args&&... args) { - return std::make_unique(std::forward(args)...); -} +template using Ptr = arena_ptr; +template using PtrVector = std::vector>; namespace ast { @@ -155,7 +152,7 @@ struct Ptrn : public Node { /// Collect patterns that bind an identifier to a value in this pattern. virtual void collect_bound_ptrns(std::vector&) const; /// Rewrites the pattern into an expression - virtual const Expr* to_expr() { return as_expr.get(); } + virtual const Expr* to_expr(Arena&) { return as_expr.get(); } /// Returns true when the pattern is trivial (e.g. always matches). virtual bool is_trivial() const = 0; /// Emits IR for the pattern, given a value to bind it to. @@ -1579,7 +1576,7 @@ struct TypedPtrn : public Ptrn { void emit(Emitter&, const thorin::Def*) const override; const artic::Type* infer(TypeChecker&) override; void bind(NameBinder&) override; - const Expr* to_expr() override; + const Expr* to_expr(Arena&) override; void resolve_summons(Summoner&) override; void print(Printer&) const override; }; @@ -1600,7 +1597,7 @@ struct IdPtrn : public Ptrn { const artic::Type* infer(TypeChecker&) override; const artic::Type* check(TypeChecker&, const artic::Type*) override; void bind(NameBinder&) override; - const Expr* to_expr() override; + const Expr* to_expr(Arena&) override; void resolve_summons(Summoner&) override; void print(Printer&) const override; }; @@ -1618,7 +1615,7 @@ struct LiteralPtrn : public Ptrn { const artic::Type* infer(TypeChecker&) override; const artic::Type* check(TypeChecker&, const artic::Type*) override; void bind(NameBinder&) override; - const Expr* to_expr() override; + const Expr* to_expr(Arena&) override; void resolve_summons(Summoner&) override {}; void print(Printer&) const override; }; diff --git a/include/artic/check.h b/include/artic/check.h index 6e57f97..70b662b 100644 --- a/include/artic/check.h +++ b/include/artic/check.h @@ -14,8 +14,8 @@ namespace artic { /// Utility class to perform bidirectional type checking. class TypeChecker : public Logger { public: - TypeChecker(Log& log, TypeTable& type_table) - : Logger(log), type_table(type_table) + TypeChecker(Log& log, TypeTable& type_table, Arena& arena) + : Logger(log), type_table(type_table), _arena(arena) {} TypeTable& type_table; @@ -82,6 +82,7 @@ class TypeChecker : public Logger { private: std::unordered_set decls_; + Arena& _arena; }; } // namespace artic diff --git a/include/artic/emit.h b/include/artic/emit.h index ab42c34..e1303ae 100644 --- a/include/artic/emit.h +++ b/include/artic/emit.h @@ -19,11 +19,12 @@ struct StructType; /// Helper class for Thorin IR generation. class Emitter : public Logger { public: - Emitter(Log& log, thorin::World& world) - : Logger(log), world(world) + Emitter(Log& log, thorin::World& world, Arena& arena) + : Logger(log), world(world), arena(arena) {} thorin::World& world; + Arena& arena; struct State { const thorin::Def* mem = nullptr; @@ -147,12 +148,13 @@ class Emitter : public Logger { /// Helper function to compile a set of files and generate an AST and a thorin module. /// Errors are reported in the log, and this function returns true on success. -bool compile( +std::tuple, bool> compile( const std::vector& file_names, const std::vector& file_data, bool warns_as_errors, bool enable_all_warns, - ast::ModDecl& program, + Arena& arena, + TypeTable& table, thorin::World& world, Log& log); diff --git a/include/artic/parser.h b/include/artic/parser.h index 8d5c0de..f27b6d4 100644 --- a/include/artic/parser.h +++ b/include/artic/parser.h @@ -17,7 +17,7 @@ namespace artic { /// Generates an AST from a stream of tokens. class Parser : public Logger { public: - Parser(Log& log, Lexer&); + Parser(Log& log, Lexer&, Arena&); /// Parses a program read from the Lexer object. /// Errors are reported by the Logger. @@ -208,6 +208,7 @@ class Parser : public Logger { Token ahead_[max_ahead]; Lexer& lexer_; Loc prev_; + Arena& _arena; }; } // namespace artic diff --git a/include/artic/summoner.h b/include/artic/summoner.h index 1c35de5..34312ed 100644 --- a/include/artic/summoner.h +++ b/include/artic/summoner.h @@ -11,8 +11,8 @@ namespace artic { class Summoner : public Logger { public: - Summoner(Log& log) - : Logger(log) + Summoner(Log& log, Arena& arena) + : Logger(log), _arena(arena) {} /// Eliminates all SummonExpr from the program @@ -28,6 +28,8 @@ class Summoner : public Logger { bool error = false; std::vector> scopes; + Arena& _arena; + friend ast::SummonExpr; friend ast::ImplicitDecl; friend ast::ModDecl; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9500adb..350fd91 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,6 +14,7 @@ add_library(libartic ../include/artic/symbol.h ../include/artic/token.h ../include/artic/types.h + arena.cpp ast.cpp bind.cpp check.cpp @@ -25,7 +26,7 @@ add_library(libartic summoner.cpp types.cpp) -set_target_properties(libartic PROPERTIES PREFIX "" CXX_STANDARD 17) +set_target_properties(libartic PROPERTIES PREFIX "" CXX_STANDARD 20) target_link_libraries(libartic PUBLIC ${Thorin_LIBRARIES}) target_include_directories(libartic PUBLIC ${Thorin_INCLUDE_DIRS} ../include) @@ -35,7 +36,7 @@ if (${COLORIZE}) endif() add_executable(artic main.cpp) -set_target_properties(artic PROPERTIES CXX_STANDARD 17) +set_target_properties(artic PROPERTIES CXX_STANDARD 20) target_compile_definitions(artic PUBLIC -DARTIC_VERSION_MAJOR=${PROJECT_VERSION_MAJOR} -DARTIC_VERSION_MINOR=${PROJECT_VERSION_MINOR}) target_link_libraries(artic PUBLIC libartic) if (Thorin_HAS_JSON_SUPPORT) diff --git a/src/arena.cpp b/src/arena.cpp new file mode 100644 index 0000000..3358bbd --- /dev/null +++ b/src/arena.cpp @@ -0,0 +1,27 @@ +#include "artic/arena.h" + +#include + +Arena::Arena() : _block_size(4096) { + _data = { malloc(_block_size) }; + _available = _block_size; +} + +Arena::~Arena() { + for (auto& ptr : _data) + free(ptr); +} + +void Arena::grow() { + _block_size *= 2; + _data.push_back( malloc(_block_size) ); + _available = _block_size; +} + +void* Arena::alloc(size_t size) { + while (size > _available) + grow(); + size_t ptr = reinterpret_cast(_data.back()) + _block_size - _available; + _available -= size; + return reinterpret_cast(ptr); +} diff --git a/src/ast.cpp b/src/ast.cpp index 77d6b81..dc5bbb7 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -619,10 +619,10 @@ bool TypedPtrn::is_trivial() const { return !ptrn || ptrn->is_trivial(); } -const Expr* TypedPtrn::to_expr() { +const Expr* TypedPtrn::to_expr(Arena& arena) { if (!ptrn) return nullptr; - return ptrn->to_expr(); + return ptrn->to_expr(arena); } void IdPtrn::collect_bound_ptrns(std::vector& bound_ptrns) const { @@ -635,7 +635,7 @@ bool IdPtrn::is_trivial() const { return !sub_ptrn || sub_ptrn->is_trivial(); } -const Expr* IdPtrn::to_expr() { +const Expr* IdPtrn::to_expr(Arena& arena) { if (as_expr) return as_expr.get(); Identifier id = decl->id; @@ -644,7 +644,7 @@ const Expr* IdPtrn::to_expr() { Path path = Path(loc, std::move(elems)); path.start_decl = decl.get(); path.is_value = true; - as_expr = make_ptr(std::move(path)); + as_expr = arena.make_ptr(std::move(path)); return as_expr.get(); } @@ -652,10 +652,10 @@ bool LiteralPtrn::is_trivial() const { return false; } -const Expr* LiteralPtrn::to_expr() { +const Expr* LiteralPtrn::to_expr(Arena& arena) { if (as_expr) return as_expr.get(); - as_expr = make_ptr(loc, lit); + as_expr = arena.make_ptr(loc, lit); return as_expr.get(); } diff --git a/src/check.cpp b/src/check.cpp index 1bbf621..ff8b2e4 100644 --- a/src/check.cpp +++ b/src/check.cpp @@ -150,7 +150,7 @@ inline std::pair remove_ptr(const Type* type) { const Type* TypeChecker::deref(Ptr& expr) { auto [ref_type, type] = remove_ref(infer(*expr)); if (ref_type) - expr = make_ptr(expr->loc, std::move(expr), type); + expr = _arena.make_ptr(expr->loc, std::move(expr), type); return type; } @@ -169,7 +169,7 @@ const Type* TypeChecker::coerce(Ptr& expr, const Type* expected) { if (auto implicit = expected->isa()) { // Only the empty tuple () can be coerced into a Summon[T] if (is_unit(expr)) { - Ptr summoned = make_ptr(expr->loc, Ptr()); + Ptr summoned = _arena.make_ptr(expr->loc, Ptr()); summoned->type = implicit->underlying; expr.swap(summoned); return implicit->underlying; @@ -193,7 +193,7 @@ const Type* TypeChecker::coerce(Ptr& expr, const Type* expected) { } if (auto implicit = tuple_t->args[i]->isa()) { - Ptr summoned = make_ptr(loc, Ptr()); + Ptr summoned = _arena.make_ptr(loc, Ptr()); summoned->type = implicit->underlying; args.push_back(std::move(summoned)); continue; @@ -201,13 +201,13 @@ const Type* TypeChecker::coerce(Ptr& expr, const Type* expected) { bad_arguments(loc, "non-implicit arguments", i, tuple_t->args.size()); } - expr = make_ptr(loc, std::move(args)); + expr = _arena.make_ptr(loc, std::move(args)); } auto type = expr->type ? expr->type : check(*expr, expected); if (type != expected) { if (type->subtype(expected)) { - expr = make_ptr(expr->loc, std::move(expr), expected); + expr = _arena.make_ptr(expr->loc, std::move(expr), expected); return expected; } else return incompatible_types(expr->loc, type, expected); @@ -1188,7 +1188,7 @@ const artic::Type* CallExpr::infer(TypeChecker& checker) { auto default_param = fn_params->args[i]->isa(); if (default_param) { auto default_expr = default_param->default_expr.get(); - args_tuple->args.push_back(std::unique_ptr(default_expr)); + args_tuple->args.push_back(arena_ptr(default_expr)); } } } diff --git a/src/emit.cpp b/src/emit.cpp index 38a1f0b..90124fe 100644 --- a/src/emit.cpp +++ b/src/emit.cpp @@ -204,7 +204,7 @@ class PtrnCompiler { assert(literal_ptrn->lit.as_string().size() + 1 == member_count); const char* str = literal_ptrn->lit.as_string().c_str(); for (size_t j = 0; j < member_count; ++j) { - auto char_ptrn = make_ptr(literal_ptrn->loc, uint8_t(str[j])); + auto char_ptrn = emitter.arena.make_ptr(literal_ptrn->loc, uint8_t(str[j])); char_ptrn->type = type->type_table.prim_type(ast::PrimType::U8); new_elems[j] = char_ptrn.get(); tmp_ptrns.emplace_back(std::move(char_ptrn)); @@ -1307,12 +1307,12 @@ const thorin::Def* ProjExpr::emit(Emitter& emitter) const { return emitter.world.extract(emitter.emit(*expr), index, emitter.debug_info(*this)); } -static inline std::pair, Ptr> dummy_case(const Loc& loc, const artic::Type* type) { +static inline std::pair, Ptr> dummy_case(const Loc& loc, const artic::Type* type, Arena& arena) { // Create a dummy wildcard pattern '_' and empty tuple '()' // for the else/break branches of an `if let`/`while let`. - auto anon_decl = make_ptr(loc, Identifier(loc, "_"), false); - auto anon_ptrn = make_ptr(loc, std::move(anon_decl), nullptr); - auto empty_tuple = make_ptr(loc, PtrVector()); + auto anon_decl = arena.make_ptr(loc, Identifier(loc, "_"), false); + auto anon_ptrn = arena.make_ptr(loc, std::move(anon_decl), nullptr); + auto empty_tuple = arena.make_ptr(loc, PtrVector()); anon_ptrn->type = type; return std::make_pair(std::move(anon_ptrn), std::move(empty_tuple)); } @@ -1338,7 +1338,7 @@ const thorin::Def* IfExpr::emit(Emitter& emitter) const { auto false_value = if_false ? emitter.emit(*if_false) : emitter.world.tuple({}); if (join) emitter.jump(join, false_value); } else { - auto [else_ptrn, empty_tuple] = dummy_case(loc, expr->type); + auto [else_ptrn, empty_tuple] = dummy_case(loc, expr->type, emitter.arena); std::vector match_cases; match_cases.emplace_back(ptrn.get(), if_true.get(), this, join); @@ -1390,7 +1390,7 @@ const thorin::Def* WhileExpr::emit(Emitter& emitter) const { emitter.emit(*body); emitter.jump(while_head); } else { - auto [else_ptrn, empty_tuple] = dummy_case(loc, expr->type); + auto [else_ptrn, empty_tuple] = dummy_case(loc, expr->type, emitter.arena); std::vector match_cases; match_cases.emplace_back(ptrn.get(), body.get(), this, while_head); @@ -2047,16 +2047,18 @@ struct MemBuf : public std::streambuf { } }; -bool compile( +std::tuple, bool> compile( const std::vector& file_names, const std::vector& file_data, bool warns_as_errors, bool enable_all_warns, - ast::ModDecl& program, + Arena& arena, + TypeTable& type_table, thorin::World& world, Log& log) { assert(file_data.size() == file_names.size()); + auto program = arena.make_ptr(); for (size_t i = 0, n = file_names.size(); i < n; ++i) { if (log.locator) log.locator->register_file(file_names[i], file_data[i]); @@ -2064,38 +2066,39 @@ bool compile( std::istream is(&mem_buf); Lexer lexer(log, file_names[i], is); - Parser parser(log, lexer); + Parser parser(log, lexer, arena); parser.warns_as_errors = warns_as_errors; auto module = parser.parse(); if (log.errors > 0) - return false; + return std::make_tuple(std::move(program), false); - program.decls.insert( - program.decls.end(), + program->decls.insert( + program->decls.end(), std::make_move_iterator(module->decls.begin()), std::make_move_iterator(module->decls.end()) ); } - program.set_super(); + program->set_super(); NameBinder name_binder(log); name_binder.warns_as_errors = warns_as_errors; if (enable_all_warns) name_binder.warn_on_shadowing = true; - TypeTable type_table; - TypeChecker type_checker(log, type_table); + TypeChecker type_checker(log, type_table, arena); type_checker.warns_as_errors = warns_as_errors; - Summoner summoner(log); + Summoner summoner(log, arena); - if (!name_binder.run(program) || !type_checker.run(program) || !summoner.run(program)) - return false; + if (!name_binder.run(*program) || !type_checker.run(*program) || !summoner.run(*program)) + return std::make_tuple(std::move(program), false); - Emitter emitter(log, world); + Emitter emitter(log, world, arena); emitter.warns_as_errors = warns_as_errors; - return emitter.run(program); + if (!emitter.run(*program)) + return std::make_tuple(std::move(program), false); + return std::make_tuple(std::move(program), true); } } // namespace artic @@ -2111,6 +2114,7 @@ bool compile( Locator locator; log::Output out(error_stream, false); Log log(out, &locator); - ast::ModDecl program; - return artic::compile(file_names, file_data, false, false, program, world, log); + Arena arena; + TypeTable type_table; + return get<1>(artic::compile(file_names, file_data, false, false, arena, type_table, world, log)); } diff --git a/src/main.cpp b/src/main.cpp index 9ef881f..ed5b7dd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -321,12 +321,13 @@ int main(int argc, char** argv) { thorin.world().set(opts.log_level); thorin.world().set(std::make_shared(std::cerr)); - ast::ModDecl program; - bool success = compile( + Arena arena; + TypeTable type_table; + auto [program, success] = compile( opts.files, file_data, opts.warns_as_errors, opts.enable_all_warns, - program, thorin.world(), log); + arena, type_table, thorin.world(), log); log.print_summary(); @@ -336,7 +337,7 @@ int main(int argc, char** argv) { Printer p(log::out); p.show_implicit_casts = opts.show_implicit_casts; p.tab = std::string(opts.tab_width, ' '); - program.print(p); + program->print(p); log::out << '\n'; log::out.stream.flush(); } diff --git a/src/parser.cpp b/src/parser.cpp index 8886069..1c35417 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -6,8 +6,8 @@ namespace artic { -Parser::Parser(Log& log, Lexer& lexer) - : Logger(log), lexer_(lexer) +Parser::Parser(Log& log, Lexer& lexer, Arena& arena) + : Logger(log), lexer_(lexer), _arena(arena) { for (int i = 0; i < max_ahead; i++) ahead_[i] = Token(Loc()); @@ -20,7 +20,7 @@ Ptr Parser::parse() { PtrVector decls; while (ahead().tag() != Token::End) decls.emplace_back(parse_decl(true)); - return make_ptr(tracker(), ast::Identifier(), std::move(decls)); + return _arena.make_ptr(tracker(), ast::Identifier(), std::move(decls)); } // Declarations -------------------------------------------------------------------- @@ -62,7 +62,7 @@ Ptr Parser::parse_let_decl() { if (accept(Token::Eq)) init = parse_expr(); expect(Token::Semi); - return make_ptr(tracker(), std::move(ptrn), std::move(init)); + return _arena.make_ptr(tracker(), std::move(ptrn), std::move(init)); } Ptr Parser::parse_fn_decl() { @@ -87,7 +87,7 @@ Ptr Parser::parse_fn_decl() { Ptr ret_type; if (accept(Token::Arrow)) { if (accept(Token::Not)) - ret_type = make_ptr(prev_); + ret_type = _arena.make_ptr(prev_); else ret_type = parse_type(); } @@ -106,8 +106,8 @@ Ptr Parser::parse_fn_decl() { expect(Token::Semi); } - auto fn = make_ptr(tracker(), std::move(filter), std::move(param), std::move(ret_type), std::move(body)); - return make_ptr(tracker(), std::move(id), std::move(fn), std::move(type_params)); + auto fn = _arena.make_ptr(tracker(), std::move(filter), std::move(param), std::move(ret_type), std::move(body)); + return _arena.make_ptr(tracker(), std::move(id), std::move(fn), std::move(type_params)); } Ptr Parser::parse_field_decl(bool is_tuple_like) { @@ -119,7 +119,7 @@ Ptr Parser::parse_field_decl(bool is_tuple_like) { Ptr init; if (accept(Token::Eq)) init = parse_expr(); - return make_ptr(tracker(), std::move(id), std::move(type), std::move(init)); + return _arena.make_ptr(tracker(), std::move(id), std::move(type), std::move(init)); } Ptr Parser::parse_struct_decl() { @@ -145,7 +145,7 @@ Ptr Parser::parse_struct_decl() { expect(Token::Semi); } - return make_ptr(tracker(), std::move(id), std::move(type_params), std::move(fields), is_tuple_like); + return _arena.make_ptr(tracker(), std::move(id), std::move(type_params), std::move(fields), is_tuple_like); } Ptr Parser::parse_option_decl() { @@ -163,7 +163,7 @@ Ptr Parser::parse_option_decl() { }); has_fields = true; } - return make_ptr(tracker(), std::move(id), std::move(param), std::move(fields), has_fields); + return _arena.make_ptr(tracker(), std::move(id), std::move(param), std::move(fields), has_fields); } Ptr Parser::parse_enum_decl() { @@ -182,7 +182,7 @@ Ptr Parser::parse_enum_decl() { }); if (options.empty()) error(tracker(), "enums require at least one alternative"); - return make_ptr(tracker(), std::move(id), std::move(type_params), std::move(options)); + return _arena.make_ptr(tracker(), std::move(id), std::move(type_params), std::move(options)); } Ptr Parser::parse_type_decl() { @@ -197,7 +197,7 @@ Ptr Parser::parse_type_decl() { expect(Token::Eq); auto aliased_type = parse_type(); expect(Token::Semi); - return make_ptr(tracker(), std::move(id), std::move(type_params), std::move(aliased_type)); + return _arena.make_ptr(tracker(), std::move(id), std::move(type_params), std::move(aliased_type)); } Ptr Parser::parse_implicit_decl() { @@ -211,7 +211,7 @@ Ptr Parser::parse_implicit_decl() { expect(Token::Eq); auto value = parse_expr(true); expect(Token::Semi); - return make_ptr(tracker(), std::move(type), std::move(value)); + return _arena.make_ptr(tracker(), std::move(type), std::move(value)); } Ptr Parser::parse_static_decl() { @@ -228,13 +228,13 @@ Ptr Parser::parse_static_decl() { if (accept(Token::Eq)) init = parse_expr(); expect(Token::Semi); - return make_ptr(tracker(), std::move(id), std::move(type), std::move(init), is_mut); + return _arena.make_ptr(tracker(), std::move(id), std::move(type), std::move(init), is_mut); } Ptr Parser::parse_type_param() { Tracker tracker(this); auto id = parse_id(); - return make_ptr(tracker(), std::move(id)); + return _arena.make_ptr(tracker(), std::move(id)); } Ptr Parser::parse_type_params() { @@ -244,7 +244,7 @@ Ptr Parser::parse_type_params() { parse_list(Token::RBracket, Token::Comma, [&] { type_params.emplace_back(parse_type_param()); }); - return make_ptr(tracker(), std::move(type_params)); + return _arena.make_ptr(tracker(), std::move(type_params)); } Ptr Parser::parse_mod_decl() { @@ -256,7 +256,7 @@ Ptr Parser::parse_mod_decl() { while (ahead().tag() != Token::End && ahead().tag() != Token::RBrace) decls.emplace_back(parse_decl(true)); expect(Token::RBrace); - return make_ptr(tracker(), std::move(id), std::move(decls)); + return _arena.make_ptr(tracker(), std::move(id), std::move(decls)); } Ptr Parser::parse_use_decl() { @@ -273,14 +273,14 @@ Ptr Parser::parse_use_decl() { log::keyword_style("use"), path, log::keyword_style("as")); } - return make_ptr(tracker(), std::move(path), std::move(id)); + return _arena.make_ptr(tracker(), std::move(path), std::move(id)); } Ptr Parser::parse_error_decl() { Tracker tracker(this); error(ahead().loc(), "expected declaration, got '{}'", ahead().string()); next(); - return make_ptr(tracker()); + return _arena.make_ptr(tracker()); } // Patterns ------------------------------------------------------------------------ @@ -295,7 +295,7 @@ Ptr Parser::parse_ptrn(bool allow_types, bool allow_implicits) { if (!allow_types) return parse_error_ptrn(); auto type = parse_prim_type(tag); - return make_ptr(type->loc, Ptr(), std::move(type)); + return _arena.make_ptr(type->loc, Ptr(), std::move(type)); } auto id = parse_path_elem(); if (ahead().tag() == Token::DblColon || @@ -307,15 +307,15 @@ Ptr Parser::parse_ptrn(bool allow_types, bool allow_implicits) { if (ahead().tag() == Token::LBrace) ptrn = parse_record_ptrn(std::move(path)); else if (allow_types) { - auto type = make_ptr(path.loc, std::move(path)); - return make_ptr(path.loc, Ptr(), std::move(type)); + auto type = _arena.make_ptr(path.loc, std::move(path)); + return _arena.make_ptr(path.loc, Ptr(), std::move(type)); } else ptrn = parse_ctor_ptrn(std::move(path)); } else { ptrn = parse_id_ptrn(std::move(id), false); if (allow_implicits && accept(Token::Eq)) { auto default_expr = parse_expr(); - ptrn = make_ptr(ptrn->loc, std::move(ptrn), std::move(default_expr)); + ptrn = _arena.make_ptr(ptrn->loc, std::move(ptrn), std::move(default_expr)); } } } @@ -339,7 +339,7 @@ Ptr Parser::parse_ptrn(bool allow_types, bool allow_implicits) { case Token::Fn: if (allow_types) { auto type = parse_type(); - return make_ptr(type->loc, Ptr(), std::move(type)); + return _arena.make_ptr(type->loc, Ptr(), std::move(type)); } [[fallthrough]]; case Token::Implicit: @@ -348,7 +348,7 @@ Ptr Parser::parse_ptrn(bool allow_types, bool allow_implicits) { return parse_error_ptrn(); eat(Token::Implicit); auto underlying = parse_ptrn(); - return make_ptr(underlying->loc, std::move(underlying)); + return _arena.make_ptr(underlying->loc, std::move(underlying)); } default: ptrn = parse_error_ptrn(); @@ -357,7 +357,7 @@ Ptr Parser::parse_ptrn(bool allow_types, bool allow_implicits) { ptrn = parse_typed_ptrn(std::move(ptrn)); if (allow_implicits && accept(Token::Eq)) { auto default_expr = parse_expr(); - ptrn = make_ptr(ptrn->loc, std::move(ptrn), std::move(default_expr)); + ptrn = _arena.make_ptr(ptrn->loc, std::move(ptrn), std::move(default_expr)); } return ptrn; } @@ -366,24 +366,24 @@ Ptr Parser::parse_typed_ptrn(Ptr&& ptrn) { Tracker tracker(this, ptrn->loc); if (accept(Token::Colon)) { auto type = parse_type(); - return make_ptr(tracker(), std::move(ptrn), std::move(type)); + return _arena.make_ptr(tracker(), std::move(ptrn), std::move(type)); } return std::move(ptrn); } Ptr Parser::parse_id_ptrn(ast::Identifier&& id, bool is_mut) { Tracker tracker(this, id.loc); - auto decl = make_ptr(tracker(), std::move(id), is_mut); + auto decl = _arena.make_ptr(tracker(), std::move(id), is_mut); Ptr sub_ptrn; if (accept(Token::As)) sub_ptrn = parse_ptrn(); - return make_ptr(tracker(), std::move(decl), std::move(sub_ptrn)); + return _arena.make_ptr(tracker(), std::move(decl), std::move(sub_ptrn)); } Ptr Parser::parse_literal_ptrn() { Tracker tracker(this); auto lit = parse_lit(); - return make_ptr(tracker(), lit); + return _arena.make_ptr(tracker(), lit); } Ptr Parser::parse_field_ptrn() { @@ -399,7 +399,7 @@ Ptr Parser::parse_field_ptrn() { expect(Token::Eq); ptrn = parse_ptrn(); } - return make_ptr(tracker(), std::move(id), std::move(ptrn)); + return _arena.make_ptr(tracker(), std::move(id), std::move(ptrn)); } Ptr Parser::parse_record_ptrn(ast::Path&& path) { @@ -413,7 +413,7 @@ Ptr Parser::parse_record_ptrn(ast::Path&& path) { auto etc = std::find_if(fields.begin(), fields.end(), [] (auto& field) { return field->is_etc(); }); if (etc != fields.end() && etc != fields.end() - 1) error((*etc)->loc, "'...' can only be used at the end of a record pattern"); - return make_ptr(tracker(), std::move(path), std::move(fields)); + return _arena.make_ptr(tracker(), std::move(path), std::move(fields)); } Ptr Parser::parse_ctor_ptrn(ast::Path&& path) { @@ -421,7 +421,7 @@ Ptr Parser::parse_ctor_ptrn(ast::Path&& path) { Ptr arg; if (ahead().tag() == Token::LParen) arg = parse_tuple_ptrn(); - return make_ptr(tracker(), std::move(path), std::move(arg)); + return _arena.make_ptr(tracker(), std::move(path), std::move(arg)); } Ptr Parser::parse_tuple_ptrn(bool allow_types, bool allow_implicits, Token::Tag beg, Token::Tag end) { @@ -435,7 +435,7 @@ Ptr Parser::parse_tuple_ptrn(bool allow_types, bool allow_implicits, args[0]->loc = tracker(); return std::move(args[0]); } - return make_ptr(tracker(), std::move(args)); + return _arena.make_ptr(tracker(), std::move(args)); } Ptr Parser::parse_array_ptrn() { @@ -446,14 +446,14 @@ Ptr Parser::parse_array_ptrn() { parse_list(Token::RBracket, Token::Comma, [&] { elems.emplace_back(parse_ptrn()); }); - return make_ptr(tracker(), std::move(elems), is_simd); + return _arena.make_ptr(tracker(), std::move(elems), is_simd); } Ptr Parser::parse_error_ptrn() { Tracker tracker(this); error(ahead().loc(), "expected pattern, got '{}'", ahead().string()); next(); - return make_ptr(tracker()); + return _arena.make_ptr(tracker()); } // Statements ---------------------------------------------------------------------- @@ -471,19 +471,19 @@ Ptr Parser::parse_stmt() { default: return parse_expr_stmt(); } - return make_ptr(tracker(), std::move(expr)); + return _arena.make_ptr(tracker(), std::move(expr)); } Ptr Parser::parse_decl_stmt() { Tracker tracker(this); auto decl = parse_decl(); - return make_ptr(tracker(), std::move(decl)); + return _arena.make_ptr(tracker(), std::move(decl)); } Ptr Parser::parse_expr_stmt() { Tracker tracker(this); auto expr = parse_expr(); - return make_ptr(tracker(), std::move(expr)); + return _arena.make_ptr(tracker(), std::move(expr)); } // Expressions --------------------------------------------------------------------- @@ -496,18 +496,18 @@ Ptr Parser::parse_typed_expr(Ptr&& expr) { Tracker tracker(this, expr->loc); eat(Token::Colon); auto type = parse_type(); - return make_ptr(tracker(), std::move(expr), std::move(type)); + return _arena.make_ptr(tracker(), std::move(expr), std::move(type)); } Ptr Parser::parse_path_expr() { auto path = parse_path(true); - return make_ptr(std::move(path)); + return _arena.make_ptr(std::move(path)); } Ptr Parser::parse_literal_expr() { Tracker tracker(this); auto lit = parse_lit(); - return make_ptr(tracker(), lit); + return _arena.make_ptr(tracker(), lit); } Ptr Parser::parse_summon_expr() { @@ -516,7 +516,7 @@ Ptr Parser::parse_summon_expr() { expect(Token::LBracket); auto t = parse_type(); expect(Token::RBracket); - return make_ptr(tracker(), std::move(t)); + return _arena.make_ptr(tracker(), std::move(t)); } Ptr Parser::parse_field_expr() { @@ -524,7 +524,7 @@ Ptr Parser::parse_field_expr() { auto id = parse_id(); expect(Token::Eq); auto expr = parse_expr(); - return make_ptr(tracker(), std::move(id), std::move(expr)); + return _arena.make_ptr(tracker(), std::move(id), std::move(expr)); } Ptr Parser::parse_record_expr(ast::Path&& path) { @@ -533,13 +533,13 @@ Ptr Parser::parse_record_expr(ast::Path&& path) { // path.loc and std::move(path) in the argument list // (argument evaluation order is not defined). auto loc = path.loc; - auto type_app = make_ptr(loc, std::move(path)); + auto type_app = _arena.make_ptr(loc, std::move(path)); eat(Token::LBrace); PtrVector fields; parse_list(Token::RBrace, Token::Comma, [&] { fields.emplace_back(parse_field_expr()); }); - return make_ptr(tracker(), std::move(type_app), std::move(fields)); + return _arena.make_ptr(tracker(), std::move(type_app), std::move(fields)); } Ptr Parser::parse_record_expr(Ptr&& expr) { @@ -550,7 +550,7 @@ Ptr Parser::parse_record_expr(Ptr&& expr) { parse_list(Token::RBrace, Token::Comma, [&] { fields.emplace_back(parse_field_expr()); }); - return make_ptr(tracker(), std::move(expr), std::move(fields)); + return _arena.make_ptr(tracker(), std::move(expr), std::move(fields)); } Ptr Parser::parse_tuple_expr() { @@ -564,7 +564,7 @@ Ptr Parser::parse_tuple_expr() { args[0]->loc = tracker(); return std::move(args[0]); } - return make_ptr(tracker(), std::move(args)); + return _arena.make_ptr(tracker(), std::move(args)); } Ptr Parser::parse_array_expr() { @@ -577,16 +577,16 @@ Ptr Parser::parse_array_expr() { auto size = parse_array_size(); expect(Token::RBracket); if (size) - return make_ptr(tracker(), std::move(elems.front()), std::move(*size), is_simd); - return make_ptr(tracker(), std::move(elems), is_simd); + return _arena.make_ptr(tracker(), std::move(elems.front()), std::move(*size), is_simd); + return _arena.make_ptr(tracker(), std::move(elems), is_simd); } else if (accept(Token::Comma)) { parse_list(Token::RBracket, Token::Comma, [&] { elems.emplace_back(parse_expr()); }); - return make_ptr(tracker(), std::move(elems), is_simd); + return _arena.make_ptr(tracker(), std::move(elems), is_simd); } else { expect(Token::RBracket); - return make_ptr(tracker(), std::move(elems), is_simd); + return _arena.make_ptr(tracker(), std::move(elems), is_simd); } } @@ -643,7 +643,7 @@ Ptr Parser::parse_block_expr() { break; } expect(Token::RBrace); - return make_ptr(tracker(), std::move(stmts), last_semi); + return _arena.make_ptr(tracker(), std::move(stmts), last_semi); } Ptr Parser::parse_fn_expr(Ptr&& filter, bool nested) { @@ -664,10 +664,10 @@ Ptr Parser::parse_fn_expr(Ptr&& filter, bool nested) { if (args.size() == 1) { ptrn = std::move(args.front()); } else { - ptrn = make_ptr(tracker(), std::move(args)); + ptrn = _arena.make_ptr(tracker(), std::move(args)); } } else if (accept(Token::LogicOr)) - ptrn = make_ptr(tracker(), PtrVector{}); + ptrn = _arena.make_ptr(tracker(), PtrVector{}); else ptrn = parse_error_ptrn(); @@ -683,13 +683,13 @@ Ptr Parser::parse_fn_expr(Ptr&& filter, bool nested) { ret_type = parse_type(); body = parse_expr(); } - return make_ptr(tracker(), std::move(filter), std::move(ptrn), std::move(ret_type), std::move(body)); + return _arena.make_ptr(tracker(), std::move(filter), std::move(ptrn), std::move(ret_type), std::move(body)); } Ptr Parser::parse_call_expr(Ptr&& callee) { Tracker tracker(this, callee->loc); auto args = parse_tuple_expr(); - return make_ptr(tracker(), std::move(callee), std::move(args)); + return _arena.make_ptr(tracker(), std::move(callee), std::move(args)); } Ptr Parser::parse_proj_expr(Ptr&& expr) { @@ -698,10 +698,10 @@ Ptr Parser::parse_proj_expr(Ptr&& expr) { if (ahead().is_literal() && ahead().literal().is_integer()) { size_t index = ahead().literal().as_integer(); eat(Token::Lit); - return make_ptr(tracker(), std::move(expr), index); + return _arena.make_ptr(tracker(), std::move(expr), index); } else { auto id = parse_id(); - return make_ptr(tracker(), std::move(expr), std::move(id)); + return _arena.make_ptr(tracker(), std::move(expr), std::move(id)); } } @@ -729,11 +729,11 @@ Ptr Parser::parse_if_expr() { auto if_true = parse_block_expr(); auto if_false = accept_else(); - return make_ptr(tracker(), std::move(ptrn), std::move(expr), std::move(if_true), std::move(if_false)); + return _arena.make_ptr(tracker(), std::move(ptrn), std::move(expr), std::move(if_true), std::move(if_false)); } else { auto [cond, if_true] = parse_cond_and_block(); auto if_false = accept_else(); - return make_ptr(tracker(), std::move(cond), std::move(if_true), std::move(if_false)); + return _arena.make_ptr(tracker(), std::move(cond), std::move(if_true), std::move(if_false)); } } @@ -742,7 +742,7 @@ Ptr Parser::parse_case_expr() { auto ptrn = parse_ptrn(); expect(Token::FatArrow); auto expr = parse_expr(); - return make_ptr(tracker(), std::move(ptrn), std::move(expr)); + return _arena.make_ptr(tracker(), std::move(ptrn), std::move(expr)); } Ptr Parser::parse_match_expr() { @@ -754,7 +754,7 @@ Ptr Parser::parse_match_expr() { parse_list(Token::RBrace, Token::Comma, [&] { cases.emplace_back(parse_case_expr()); }); - return make_ptr(tracker(), std::move(arg), std::move(cases)); + return _arena.make_ptr(tracker(), std::move(arg), std::move(cases)); } Ptr Parser::parse_while_expr() { @@ -766,10 +766,10 @@ Ptr Parser::parse_while_expr() { auto expr = parse_expr(false); auto body = parse_block_expr(); - return make_ptr(tracker(), std::move(ptrn), std::move(expr), std::move(body)); + return _arena.make_ptr(tracker(), std::move(ptrn), std::move(expr), std::move(body)); } else { auto[cond, body] = parse_cond_and_block(); - return make_ptr(tracker(), std::move(cond), std::move(body)); + return _arena.make_ptr(tracker(), std::move(cond), std::move(body)); } } @@ -787,15 +787,15 @@ Ptr Parser::parse_for_expr() { ptrn = parse_tuple_ptrn(false, false, Token::For, Token::In); else { eat(Token::For); - ptrn = make_ptr(tracker(), PtrVector{}); + ptrn = _arena.make_ptr(tracker(), PtrVector{}); } auto expr = parse_expr(); auto call_loc = expr->loc; - Ptr call(expr->isa() ? expr.release()->as() : nullptr); + Ptr call(expr->isa() ? expr->as() : nullptr); if (!call) { error(ahead().loc(), "invalid for loop expression"); - return make_ptr(tracker()); + return _arena.make_ptr(tracker()); } Ptr body; @@ -806,29 +806,29 @@ Ptr Parser::parse_for_expr() { auto lambda_loc = body->loc; // Cannot use body->loc directly because std::move(body) might be executed first - auto lambda = make_ptr(lambda_loc, nullptr, std::move(ptrn), nullptr, std::move(body)); + auto lambda = _arena.make_ptr(lambda_loc, nullptr, std::move(ptrn), nullptr, std::move(body)); - Ptr callee(call->callee.release()); - call->callee = make_ptr(call_loc, std::move(callee), std::move(lambda)); - return make_ptr(tracker(), std::move(call)); + Ptr callee(call->callee.get()); + call->callee = _arena.make_ptr(call_loc, std::move(callee), std::move(lambda)); + return _arena.make_ptr(tracker(), std::move(call)); } Ptr Parser::parse_break_expr() { Tracker tracker(this); eat(Token::Break); - return make_ptr(tracker()); + return _arena.make_ptr(tracker()); } Ptr Parser::parse_continue_expr() { Tracker tracker(this); eat(Token::Continue); - return make_ptr(tracker()); + return _arena.make_ptr(tracker()); } Ptr Parser::parse_return_expr() { Tracker tracker(this); eat(Token::Return); - return make_ptr(tracker()); + return _arena.make_ptr(tracker()); } Ptr Parser::parse_primary_expr(bool allow_structs, bool allow_casts) { @@ -910,14 +910,14 @@ Ptr Parser::parse_prefix_expr(bool allow_structs) { if (tag == ast::UnaryExpr::AddrOf && accept(Token::Mut)) tag = ast::UnaryExpr::AddrOfMut; auto expr = parse_primary_expr(allow_structs, false); - return make_ptr(tracker(), tag, std::move(expr)); + return _arena.make_ptr(tracker(), tag, std::move(expr)); } Ptr Parser::parse_postfix_expr(Ptr&& expr) { Tracker tracker(this, expr->loc); auto tag = ast::UnaryExpr::tag_from_token(ahead(), false); next(); - return make_ptr(tracker(), tag, std::move(expr)); + return _arena.make_ptr(tracker(), tag, std::move(expr)); } Ptr Parser::parse_binary_expr(bool allow_structs, int max_prec) { @@ -932,7 +932,7 @@ Ptr Parser::parse_binary_expr(bool allow_structs, int max_prec) { next(); auto right = parse_binary_expr(allow_structs, prec - 1); - left = make_ptr(tracker(), tag, std::move(left), std::move(right)); + left = _arena.make_ptr(tracker(), tag, std::move(left), std::move(right)); } return left; } @@ -943,7 +943,7 @@ Ptr Parser::parse_filter_expr(Ptr&& filter) { if (auto call_expr = expr->isa()) { if (call_expr->callee->isa()) warn(filter->loc, "redundant filter annotation"); - call_expr->callee = make_ptr(tracker(), std::move(filter), std::move(call_expr->callee)); + call_expr->callee = _arena.make_ptr(tracker(), std::move(filter), std::move(call_expr->callee)); } else error(expr->loc, "invalid filter expression"); return expr; @@ -953,7 +953,7 @@ Ptr Parser::parse_cast_expr(Ptr&& expr) { Tracker tracker(this, expr->loc); eat(Token::As); auto type = parse_type(); - return make_ptr(tracker(), std::move(expr), std::move(type)); + return _arena.make_ptr(tracker(), std::move(expr), std::move(type)); } Ptr Parser::parse_asm_expr() { @@ -1014,7 +1014,7 @@ Ptr Parser::parse_asm_expr() { error(ahead().loc(), "expected ':', or ')' in assembly expression"); done: - return make_ptr( + return _arena.make_ptr( tracker(), std::move(src), std::move(ins), std::move(outs), std::move(clobs), std::move(opts)); @@ -1024,7 +1024,7 @@ Ptr Parser::parse_error_expr() { Tracker tracker(this); error(ahead().loc(), "expected expression, got '{}'", ahead().string()); next(); - return make_ptr(tracker()); + return _arena.make_ptr(tracker()); } // Types --------------------------------------------------------------------------- @@ -1057,7 +1057,7 @@ Ptr Parser::parse_named_type() { Ptr Parser::parse_prim_type(ast::PrimType::Tag tag) { Tracker tracker(this); next(); - return make_ptr(tracker(), tag); + return _arena.make_ptr(tracker(), tag); } Ptr Parser::parse_tuple_type() { @@ -1071,7 +1071,7 @@ Ptr Parser::parse_tuple_type() { args[0]->loc = tracker(); return std::move(args[0]); } - return make_ptr(tracker(), std::move(args)); + return _arena.make_ptr(tracker(), std::move(args)); } Ptr Parser::parse_array_type() { @@ -1084,11 +1084,11 @@ Ptr Parser::parse_array_type() { auto size = parse_array_size(); expect(Token::RBracket); if (size) - return make_ptr(tracker(), std::move(elem), std::move(*size), is_simd); - return make_ptr(tracker(), std::move(elem)); + return _arena.make_ptr(tracker(), std::move(elem), std::move(*size), is_simd); + return _arena.make_ptr(tracker(), std::move(elem)); } else { expect(Token::RBracket); - return make_ptr(tracker(), std::move(elem)); + return _arena.make_ptr(tracker(), std::move(elem)); } } @@ -1103,10 +1103,10 @@ Ptr Parser::parse_fn_type() { expect(Token::Arrow); Ptr to; if (accept(Token::Not)) - to = make_ptr(prev_); + to = _arena.make_ptr(prev_); else to = parse_type(); - return make_ptr(tracker(), std::move(from), std::move(to)); + return _arena.make_ptr(tracker(), std::move(from), std::move(to)); } Ptr Parser::parse_ptr_type() { @@ -1120,23 +1120,23 @@ Ptr Parser::parse_ptr_type() { if (ahead().tag() == Token::AddrSpace) addr_space = parse_addr_space(); auto pointee = parse_type(); - auto inner_ptr = make_ptr(tracker(), std::move(pointee), is_mut, addr_space); + auto inner_ptr = _arena.make_ptr(tracker(), std::move(pointee), is_mut, addr_space); return double_ptr - ? make_ptr(tracker(), std::move(inner_ptr), false, 0) + ? _arena.make_ptr(tracker(), std::move(inner_ptr), false, 0) : std::move(inner_ptr); } Ptr Parser::parse_type_app() { Tracker tracker(this); auto path = parse_path(); - return make_ptr(tracker(), std::move(path)); + return _arena.make_ptr(tracker(), std::move(path)); } Ptr Parser::parse_error_type() { Tracker tracker(this); error(ahead().loc(), "expected type, got '{}'", ahead().string()); next(); - return make_ptr(tracker()); + return _arena.make_ptr(tracker()); } Ptr Parser::parse_filter() { @@ -1147,7 +1147,7 @@ Ptr Parser::parse_filter() { expr = parse_expr(); expect(Token::RParen); } - return make_ptr(tracker(), std::move(expr)); + return _arena.make_ptr(tracker(), std::move(expr)); } Ptr Parser::parse_attr_list() { @@ -1158,7 +1158,7 @@ Ptr Parser::parse_attr_list() { parse_list(Token::RBracket, Token::Comma, [&] { attrs.emplace_back(parse_attr()); }); - return make_ptr(tracker(), std::move(attrs)); + return _arena.make_ptr(tracker(), std::move(attrs)); } Ptr Parser::parse_attr() { @@ -1172,13 +1172,13 @@ Ptr Parser::parse_attr() { if (ahead().tag() == Token::Lit) { auto lit = ahead().literal(); eat(Token::Lit); - return make_ptr(tracker(), std::move(name), lit); + return _arena.make_ptr(tracker(), std::move(name), lit); } else if (ahead().tag() == Token::Id) { auto path = parse_path(); - return make_ptr(tracker(), std::move(name), std::move(path)); + return _arena.make_ptr(tracker(), std::move(name), std::move(path)); } else { error(ahead().loc(), "expected attribute value, got '{}'", ahead().string()); - return make_ptr(tracker(), std::move(name), PtrVector()); + return _arena.make_ptr(tracker(), std::move(name), PtrVector()); } } else { PtrVector args; @@ -1187,7 +1187,7 @@ Ptr Parser::parse_attr() { args.emplace_back(parse_attr()); }); } - return make_ptr(tracker(), std::move(name), std::move(args)); + return _arena.make_ptr(tracker(), std::move(name), std::move(args)); } } diff --git a/src/summoner.cpp b/src/summoner.cpp index 26f61eb..3d32c15 100644 --- a/src/summoner.cpp +++ b/src/summoner.cpp @@ -220,7 +220,7 @@ void IdPtrn::resolve_summons(artic::Summoner& summoner) { } void ImplicitParamPtrn::resolve_summons(artic::Summoner& summoner) { - summoner.insert(underlying->type, underlying->to_expr()); + summoner.insert(underlying->type, underlying->to_expr(summoner._arena)); } void DefaultParamPtrn::resolve_summons(artic::Summoner& summoner) {