diff --git a/include/pocketpy/compiler.h b/include/pocketpy/compiler.h index 133171a0..3faf07c5 100644 --- a/include/pocketpy/compiler.h +++ b/include/pocketpy/compiler.h @@ -20,7 +20,8 @@ class Compiler { PK_ALWAYS_PASS_BY_POINTER(Compiler) inline static PrattRule rules[kTokenCount]; - std::unique_ptr lexer; + + Lexer lexer; stack contexts; VM* vm; bool unknown_global_scope; // for eval/exec() call @@ -39,7 +40,7 @@ class Compiler { void advance(int delta=1) { i += delta; } CodeEmitContext* ctx() { return &contexts.top(); } - CompileMode mode() const{ return lexer->src->mode; } + CompileMode mode() const{ return lexer.src->mode; } NameScope name_scope() const; CodeObject_ push_global_context(); FuncDecl_ push_f_context(Str name); @@ -61,8 +62,9 @@ class Compiler { Expr_ EXPR_VARS(); // special case for `for loop` and `comp` template - std::unique_ptr make_expr(Args&&... args) { - std::unique_ptr expr = std::make_unique(std::forward(args)...); + unique_ptr_64 make_expr(Args&&... args) { + void* p = pool64_alloc(sizeof(T)); + unique_ptr_64 expr(new (p) T(std::forward(args)...)); expr->line = prev().line; return expr; } @@ -70,7 +72,7 @@ class Compiler { template void _consume_comp(Expr_ expr){ static_assert(std::is_base_of::value); - std::unique_ptr ce = make_expr(); + unique_ptr_64 ce = make_expr(); ce->expr = std::move(expr); ce->vars = EXPR_VARS(); consume(TK("in")); @@ -130,9 +132,9 @@ class Compiler { PyObject* to_object(const TokenValue& value); PyObject* read_literal(); - void SyntaxError(Str msg){ lexer->throw_err("SyntaxError", msg, err().line, err().start); } - void SyntaxError(){ lexer->throw_err("SyntaxError", "invalid syntax", err().line, err().start); } - void IndentationError(Str msg){ lexer->throw_err("IndentationError", msg, err().line, err().start); } + void SyntaxError(Str msg){ lexer.throw_err("SyntaxError", msg, err().line, err().start); } + void SyntaxError(){ lexer.throw_err("SyntaxError", "invalid syntax", err().line, err().start); } + void IndentationError(Str msg){ lexer.throw_err("IndentationError", msg, err().line, err().start); } public: Compiler(VM* vm, std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope=false); diff --git a/include/pocketpy/expr.h b/include/pocketpy/expr.h index 8046e86a..4eba89f6 100644 --- a/include/pocketpy/expr.h +++ b/include/pocketpy/expr.h @@ -10,7 +10,47 @@ namespace pkpy{ struct CodeEmitContext; struct Expr; -typedef std::unique_ptr Expr_; + +#define PK_POOL64_DELETE(ptr) if(ptr != nullptr) { ptr->~T(); pool64_dealloc(ptr); ptr = nullptr; } + +template +class unique_ptr_64{ + T* ptr; +public: + unique_ptr_64(): ptr(nullptr) {} + unique_ptr_64(T* ptr): ptr(ptr) {} + T* operator->() const { return ptr; } + T* get() const { return ptr; } + T* release() { T* p = ptr; ptr = nullptr; return p; } + + unique_ptr_64(const unique_ptr_64&) = delete; + unique_ptr_64& operator=(const unique_ptr_64&) = delete; + + bool operator==(std::nullptr_t) const { return ptr == nullptr; } + bool operator!=(std::nullptr_t) const { return ptr != nullptr; } + + ~unique_ptr_64(){ PK_POOL64_DELETE(ptr) } + + template + unique_ptr_64(unique_ptr_64&& other): ptr(other.release()) {} + + operator bool() const { return ptr != nullptr; } + + template + unique_ptr_64& operator=(unique_ptr_64&& other) { + PK_POOL64_DELETE(ptr) + ptr = other.release(); + return *this; + } + + unique_ptr_64& operator=(std::nullptr_t) { + PK_POOL64_DELETE(ptr) + ptr = nullptr; + return *this; + } +}; + +typedef unique_ptr_64 Expr_; struct Expr{ int line = 0; diff --git a/src/compiler.cpp b/src/compiler.cpp index 39fca240..bfa7c58d 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -9,7 +9,7 @@ namespace pkpy{ } CodeObject_ Compiler::push_global_context(){ - CodeObject_ co = std::make_shared(lexer->src, lexer->src->filename); + CodeObject_ co = std::make_shared(lexer.src, lexer.src->filename); co->start_line = i==0 ? 1 : prev().line; contexts.push(CodeEmitContext(vm, co, contexts.size())); return co; @@ -17,7 +17,7 @@ namespace pkpy{ FuncDecl_ Compiler::push_f_context(Str name){ FuncDecl_ decl = std::make_shared(); - decl->code = std::make_shared(lexer->src, name); + decl->code = std::make_shared(lexer.src, name); decl->code->start_line = i==0 ? 1 : prev().line; decl->nested = name_scope() == NAME_LOCAL; contexts.push(CodeEmitContext(vm, decl->code, contexts.size())); @@ -912,7 +912,7 @@ __EAT_DOTS_END: } ctx()->emit_(OP_WITH_ENTER, BC_NOARG, prev().line); // [ .__enter__() ] - if(as_name){ + if(as_name != nullptr){ bool ok = as_name->emit_store(ctx()); if(!ok) SyntaxError(); }else{ @@ -1178,13 +1178,11 @@ __EAT_DOTS_END: return nullptr; } - Compiler::Compiler(VM* vm, std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope){ + Compiler::Compiler(VM* vm, std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope) + :lexer(vm, std::make_shared(source, filename, mode)){ this->vm = vm; this->used = false; this->unknown_global_scope = unknown_global_scope; - this->lexer = std::make_unique( - vm, std::make_shared(source, filename, mode) - ); init_pratt_rules(); } @@ -1193,7 +1191,7 @@ __EAT_DOTS_END: PK_ASSERT(!used) used = true; - tokens = lexer->run(); + tokens = lexer.run(); CodeObject_ code = push_global_context(); advance(); // skip @sof, so prev() is always valid