diff --git a/include/pocketpy/common/vector.hpp b/include/pocketpy/common/vector.hpp index 12862c06..f1ed4d5c 100644 --- a/include/pocketpy/common/vector.hpp +++ b/include/pocketpy/common/vector.hpp @@ -254,7 +254,7 @@ struct vector { _data[_size].~T(); } - T popx_back() { + [[nodiscard]] T popx_back() { T retval = std::move(back()); pop_back(); return retval; diff --git a/include/pocketpy/compiler/compiler.hpp b/include/pocketpy/compiler/compiler.hpp index 2ebfc1df..19e701a7 100644 --- a/include/pocketpy/compiler/compiler.hpp +++ b/include/pocketpy/compiler/compiler.hpp @@ -61,18 +61,19 @@ class Compiler { /*************************************************/ void EXPR(); void EXPR_TUPLE(bool allow_slice = false); - Expr_ EXPR_VARS(); // special case for `for loop` and `comp` + Expr* EXPR_VARS(); // special case for `for loop` and `comp` template - unique_ptr_128 make_expr(Args&&... args) { + T* make_expr(Args&&... args) { static_assert(sizeof(T) <= kPoolExprBlockSize); + static_assert(std::is_base_of_v); void* p = PoolExpr_alloc(); - unique_ptr_128 expr(new (p) T(std::forward(args)...)); + T* expr = new (p) T(std::forward(args)...); expr->line = prev().line; return expr; } - void consume_comp(unique_ptr_128 ce, Expr_ expr); + void consume_comp(CompExpr* ce, Expr* expr); void exprLiteral(); void exprLong(); diff --git a/include/pocketpy/compiler/expr.hpp b/include/pocketpy/compiler/expr.hpp index 11db4362..058ef532 100644 --- a/include/pocketpy/compiler/expr.hpp +++ b/include/pocketpy/compiler/expr.hpp @@ -8,75 +8,19 @@ namespace pkpy { struct CodeEmitContext; struct Expr; -template -class unique_ptr_128 { - T* ptr; - -public: - unique_ptr_128() : ptr(nullptr) {} - - unique_ptr_128(T* ptr) : ptr(ptr) {} - - T* operator->() const { return ptr; } - - T* get() const { return ptr; } - - T* detach() { - T* p = ptr; - ptr = nullptr; - return p; - } - - unique_ptr_128(const unique_ptr_128&) = delete; - unique_ptr_128& operator= (const unique_ptr_128&) = delete; - - bool operator== (std::nullptr_t) const { return ptr == nullptr; } - - bool operator!= (std::nullptr_t) const { return ptr != nullptr; } - - ~unique_ptr_128() { - if(ptr) { - ptr->~T(); - PoolExpr_dealloc(ptr); - } - } - - template - unique_ptr_128(unique_ptr_128&& other) : ptr(other.detach()) {} - - operator bool () const { return ptr != nullptr; } - - template - unique_ptr_128& operator= (unique_ptr_128&& other) { - if(ptr) { - ptr->~T(); - PoolExpr_dealloc(ptr); - }; - ptr = other.detach(); - return *this; - } - - unique_ptr_128& operator= (std::nullptr_t) { - if(ptr) { - ptr->~T(); - PoolExpr_dealloc(ptr); - } - ptr = nullptr; - return *this; - } -}; - -typedef unique_ptr_128 Expr_; -typedef small_vector Expr_vector; - -template <> -constexpr inline bool is_trivially_relocatable_v = true; +typedef small_vector Expr_vector; struct Expr { int line = 0; virtual ~Expr() = default; virtual void emit_(CodeEmitContext* ctx) = 0; + Expr() = default; + Expr(const Expr&) = delete; + Expr(Expr&&) = delete; + Expr& operator=(const Expr&) = delete; + Expr& operator=(Expr&&) = delete; + virtual bool is_literal() const { return false; } virtual bool is_json_object() const { return false; } @@ -106,11 +50,17 @@ struct Expr { [[nodiscard]] virtual bool emit_store_inplace(CodeEmitContext* ctx) { return emit_store(ctx); } }; +inline void delete_expr(Expr* p){ + if(!p) return; + p->Expr::~Expr(); + PoolExpr_dealloc(p); +} + struct CodeEmitContext { VM* vm; FuncDecl_ func; // optional CodeObject_ co; // 1 CodeEmitContext <=> 1 CodeObject_ - vector s_expr; + vector s_expr; int level; vector global_names; @@ -125,7 +75,7 @@ struct CodeEmitContext { int get_loop() const; CodeBlock* enter_block(CodeBlockType type); void exit_block(); - void emit_expr(); // clear the expression stack and generate bytecode + void emit_expr(bool emit = true); // clear the expression stack and generate bytecode int emit_(Opcode opcode, uint16_t arg, int line, bool is_virtual = false); void revert_last_emit_(); int emit_int(i64 value, int line); @@ -152,19 +102,33 @@ struct NameExpr : Expr { bool is_name() const override { return true; } }; -struct InvertExpr : Expr { - Expr_ child; +struct _UnaryExpr : Expr { + Expr* child; + _UnaryExpr(Expr* child) : child(child) {} + _UnaryExpr() : child(nullptr) {} + ~_UnaryExpr() { delete_expr(child); } +}; - InvertExpr(Expr_&& child) : child(std::move(child)) {} +struct _BinaryExpr : Expr { + Expr* lhs; + Expr* rhs; + _BinaryExpr(Expr* lhs, Expr* rhs) : lhs(lhs), rhs(rhs) {} + _BinaryExpr() : lhs(nullptr), rhs(nullptr) {} + ~_BinaryExpr() { + delete_expr(lhs); + delete_expr(rhs); + } +}; +struct InvertExpr : _UnaryExpr { + using _UnaryExpr::_UnaryExpr; void emit_(CodeEmitContext* ctx) override; }; -struct StarredExpr : Expr { +struct StarredExpr : _UnaryExpr { int level; - Expr_ child; - StarredExpr(int level, Expr_&& child) : level(level), child(std::move(child)) {} + StarredExpr(Expr* child, int level) : _UnaryExpr(child), level(level) {} int star_level() const override { return level; } @@ -172,23 +136,18 @@ struct StarredExpr : Expr { bool emit_store(CodeEmitContext* ctx) override; }; -struct NotExpr : Expr { - Expr_ child; - - NotExpr(Expr_&& child) : child(std::move(child)) {} - +struct NotExpr : _UnaryExpr { + using _UnaryExpr::_UnaryExpr; void emit_(CodeEmitContext* ctx) override; }; -struct AndExpr : Expr { - Expr_ lhs; - Expr_ rhs; +struct AndExpr : _BinaryExpr { + using _BinaryExpr::_BinaryExpr; void emit_(CodeEmitContext* ctx) override; }; -struct OrExpr : Expr { - Expr_ lhs; - Expr_ rhs; +struct OrExpr : _BinaryExpr { + using _BinaryExpr::_BinaryExpr; void emit_(CodeEmitContext* ctx) override; }; @@ -240,30 +199,40 @@ struct LiteralExpr : Expr { bool is_json_object() const override { return true; } }; -struct NegatedExpr : Expr { - Expr_ child; - - NegatedExpr(Expr_&& child) : child(std::move(child)) {} - +struct NegatedExpr : _UnaryExpr { + using _UnaryExpr::_UnaryExpr; void emit_(CodeEmitContext* ctx) override; - bool is_json_object() const override { return child->is_literal(); } }; struct SliceExpr : Expr { - Expr_ start; - Expr_ stop; - Expr_ step; + Expr* start = nullptr; + Expr* stop = nullptr; + Expr* step = nullptr; + void emit_(CodeEmitContext* ctx) override; + + ~SliceExpr() { + delete_expr(start); + delete_expr(stop); + delete_expr(step); + } }; struct DictItemExpr : Expr { - Expr_ key; // maybe nullptr if it is **kwargs - Expr_ value; + Expr* key; // maybe nullptr if it is **kwargs + Expr* value; + + DictItemExpr(): key(nullptr), value(nullptr) {} int star_level() const override { return value->star_level(); } void emit_(CodeEmitContext* ctx) override; + + ~DictItemExpr() { + delete_expr(key); + delete_expr(value); + } }; struct SequenceExpr : Expr { @@ -278,6 +247,10 @@ struct SequenceExpr : Expr { item->emit_(ctx); ctx->emit_(opcode(), items.size(), line); } + + ~SequenceExpr() { + for(Expr* item: items) delete_expr(item); + } }; struct ListExpr : SequenceExpr { @@ -330,15 +303,22 @@ struct TupleExpr : SequenceExpr { }; struct CompExpr : Expr { - Expr_ expr; // loop expr - Expr_ vars; // loop vars - Expr_ iter; // loop iter - Expr_ cond; // optional if condition + Expr* expr = nullptr; // loop expr + Expr* vars = nullptr; // loop vars + Expr* iter = nullptr; // loop iter + Expr* cond = nullptr; // optional if condition virtual Opcode op0() = 0; virtual Opcode op1() = 0; void emit_(CodeEmitContext* ctx) override; + + ~CompExpr() { + delete_expr(expr); + delete_expr(vars); + delete_expr(iter); + delete_expr(cond); + } }; struct ListCompExpr : CompExpr { @@ -379,10 +359,8 @@ struct FStringExpr : Expr { void emit_(CodeEmitContext* ctx) override; }; -struct SubscrExpr : Expr { - Expr_ a; - Expr_ b; - +struct SubscrExpr : _BinaryExpr { + using _BinaryExpr::_BinaryExpr; bool is_subscr() const override { return true; } void emit_(CodeEmitContext* ctx) override; @@ -393,11 +371,10 @@ struct SubscrExpr : Expr { bool emit_store_inplace(CodeEmitContext* ctx) override; }; -struct AttribExpr : Expr { - Expr_ a; - StrName b; +struct AttribExpr : _UnaryExpr { + StrName name; - AttribExpr(Expr_ a, StrName b) : a(std::move(a)), b(b) {} + AttribExpr(Expr* child, StrName name) : _UnaryExpr(child), name(name) {} void emit_(CodeEmitContext* ctx) override; bool emit_del(CodeEmitContext* ctx) override; @@ -411,32 +388,34 @@ struct AttribExpr : Expr { }; struct CallExpr : Expr { - Expr_ callable; + Expr* callable; Expr_vector args; // **a will be interpreted as a special keyword argument: {"**": a} - vector> kwargs; + vector> kwargs; void emit_(CodeEmitContext* ctx) override; + + ~CallExpr() { + delete_expr(callable); + for(Expr* arg: args) delete_expr(arg); + for(auto [_, arg]: kwargs) delete_expr(arg); + } }; -struct GroupedExpr : Expr { - Expr_ a; +struct GroupedExpr : _UnaryExpr { + using _UnaryExpr::_UnaryExpr; + void emit_(CodeEmitContext* ctx) override { child->emit_(ctx); } - GroupedExpr(Expr_&& a) : a(std::move(a)) {} + bool emit_del(CodeEmitContext* ctx) override { return child->emit_del(ctx); } - void emit_(CodeEmitContext* ctx) override { a->emit_(ctx); } - - bool emit_del(CodeEmitContext* ctx) override { return a->emit_del(ctx); } - - bool emit_store(CodeEmitContext* ctx) override { return a->emit_store(ctx); } + bool emit_store(CodeEmitContext* ctx) override { return child->emit_store(ctx); } }; -struct BinaryExpr : Expr { +struct BinaryExpr : _BinaryExpr { TokenIndex op; - Expr_ lhs; - Expr_ rhs; bool inplace; - BinaryExpr(bool inplace = false) : inplace(inplace) {} + BinaryExpr(TokenIndex op, bool inplace = false) + : _BinaryExpr(), op(op), inplace(inplace) {} bool is_compare() const override; void _emit_compare(CodeEmitContext*, small_vector_2&); @@ -444,10 +423,17 @@ struct BinaryExpr : Expr { }; struct TernaryExpr : Expr { - Expr_ cond; - Expr_ true_expr; - Expr_ false_expr; + Expr* cond = nullptr; + Expr* true_expr = nullptr; + Expr* false_expr = nullptr; + void emit_(CodeEmitContext* ctx) override; + + ~TernaryExpr() { + delete_expr(cond); + delete_expr(true_expr); + delete_expr(false_expr); + } }; } // namespace pkpy diff --git a/src/compiler/compiler.cpp b/src/compiler/compiler.cpp index 2d7e78fa..f68181d5 100644 --- a/src/compiler/compiler.cpp +++ b/src/compiler/compiler.cpp @@ -31,7 +31,7 @@ FuncDecl_ Compiler::push_f_context(Str name) { } void Compiler::pop_context() { - if(!ctx()->s_expr.empty()) { throw std::runtime_error("!ctx()->s_expr.empty()"); } + assert(ctx()->s_expr.empty()); // add a `return None` in the end as a guard // previously, we only do this if the last opcode is not a return // however, this is buggy...since there may be a jump to the end (out of bound) even if the last opcode is a return @@ -211,7 +211,7 @@ void Compiler::EXPR_TUPLE(bool allow_slice) { } // special case for `for loop` and `comp` -Expr_ Compiler::EXPR_VARS() { +Expr* Compiler::EXPR_VARS() { Expr_vector items; do { consume(TK("@id")); @@ -276,8 +276,7 @@ void Compiler::exprTernary() { } void Compiler::exprBinaryOp() { - auto e = make_expr(); - e->op = prev().type; + auto e = make_expr(prev().type); e->lhs = ctx()->s_expr.popx_back(); parse_expression(rules[e->op].precedence + 1); e->rhs = ctx()->s_expr.popx_back(); @@ -286,17 +285,19 @@ void Compiler::exprBinaryOp() { void Compiler::exprNot() { parse_expression(PREC_LOGICAL_NOT + 1); - ctx()->s_expr.push_back(make_expr(ctx()->s_expr.popx_back())); + NotExpr* e = make_expr(ctx()->s_expr.popx_back()); + ctx()->s_expr.push_back(e); } void Compiler::exprUnaryOp() { TokenIndex op = prev().type; parse_expression(PREC_UNARY + 1); + vector& s_expr = ctx()->s_expr; switch(op) { - case TK("-"): ctx()->s_expr.push_back(make_expr(ctx()->s_expr.popx_back())); break; - case TK("~"): ctx()->s_expr.push_back(make_expr(ctx()->s_expr.popx_back())); break; - case TK("*"): ctx()->s_expr.push_back(make_expr(1, ctx()->s_expr.popx_back())); break; - case TK("**"): ctx()->s_expr.push_back(make_expr(2, ctx()->s_expr.popx_back())); break; + case TK("-"): s_expr.push_back(make_expr(s_expr.popx_back())); break; + case TK("~"): s_expr.push_back(make_expr(s_expr.popx_back())); break; + case TK("*"): s_expr.push_back(make_expr(s_expr.popx_back(), 1)); break; + case TK("**"): s_expr.push_back(make_expr(s_expr.popx_back(), 2)); break; default: assert(false); } } @@ -307,11 +308,11 @@ void Compiler::exprGroup() { match_newlines_repl(); consume(TK(")")); if(ctx()->s_expr.back()->is_tuple()) return; - Expr_ g = make_expr(ctx()->s_expr.popx_back()); + Expr* g = make_expr(ctx()->s_expr.popx_back()); ctx()->s_expr.push_back(std::move(g)); } -void Compiler::consume_comp(unique_ptr_128 ce, Expr_ expr) { +void Compiler::consume_comp(CompExpr* ce, Expr* expr) { ce->expr = std::move(expr); ce->vars = EXPR_VARS(); consume(TK("in")); @@ -358,7 +359,7 @@ void Compiler::exprMap() { int star_level = ctx()->s_expr.back()->star_level(); if(star_level == 2 || curr().type == TK(":")) { parsing_dict = true; } if(parsing_dict) { - auto dict_item = make_expr(); + DictItemExpr* dict_item = make_expr(); if(star_level == 2) { dict_item->key = nullptr; dict_item->value = ctx()->s_expr.popx_back(); @@ -401,7 +402,7 @@ void Compiler::exprCall() { if(curr().type == TK(")")) break; if(curr().type == TK("@id") && next().type == TK("=")) { consume(TK("@id")); - Str key = prev().str(); + StrName key(prev().sv()); consume(TK("=")); EXPR(); e->kwargs.push_back({key, ctx()->s_expr.popx_back()}); @@ -476,9 +477,9 @@ void Compiler::exprSlice1() { void Compiler::exprSubscr() { auto e = make_expr(); match_newlines_repl(); - e->a = ctx()->s_expr.popx_back(); // a + e->lhs = ctx()->s_expr.popx_back(); // a EXPR_TUPLE(true); - e->b = ctx()->s_expr.popx_back(); // a[] + e->rhs = ctx()->s_expr.popx_back(); // a[] match_newlines_repl(); consume(TK("]")); ctx()->s_expr.push_back(std::move(e)); @@ -650,7 +651,7 @@ void Compiler::compile_while_loop() { } void Compiler::compile_for_loop() { - Expr_ vars = EXPR_VARS(); + Expr* vars = EXPR_VARS(); consume(TK("in")); EXPR_TUPLE(); ctx()->emit_expr(); @@ -764,14 +765,14 @@ bool Compiler::try_compile_assignment() { case TK("&="): case TK("|="): case TK("^="): { - Expr* lhs_p = ctx()->s_expr.back().get(); + Expr* lhs_p = ctx()->s_expr.back(); if(lhs_p->is_starred()) SyntaxError(); if(ctx()->is_compiling_class) SyntaxError("can't use inplace operator in class definition"); advance(); // a[x] += 1; a and x should be evaluated only once // a.x += 1; a should be evaluated only once - auto e = make_expr(true); // inplace=true - e->op = prev().type - 1; // -1 to remove = + // -1 to remove =; inplace=true + auto e = make_expr(prev().type - 1, true); e->lhs = ctx()->s_expr.popx_back(); EXPR_TUPLE(); e->rhs = ctx()->s_expr.popx_back(); @@ -788,7 +789,7 @@ bool Compiler::try_compile_assignment() { n += 1; } // stack size is n+1 - Expr_ val = ctx()->s_expr.popx_back(); + Expr* val = ctx()->s_expr.popx_back(); val->emit_(ctx()); for(int j = 1; j < n; j++) ctx()->emit_(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE); @@ -894,7 +895,7 @@ void Compiler::compile_stmt() { } break; case TK("del"): { EXPR_TUPLE(); - Expr_ e = ctx()->s_expr.popx_back(); + Expr* e = ctx()->s_expr.popx_back(); bool ok = e->emit_del(ctx()); if(!ok) SyntaxError(); consume_end_stmt(); @@ -903,7 +904,7 @@ void Compiler::compile_stmt() { EXPR(); // [ ] ctx()->emit_expr(); ctx()->enter_block(CodeBlockType::CONTEXT_MANAGER); - Expr_ as_name; + Expr* as_name = nullptr;; if(match(TK("as"))) { consume(TK("@id")); as_name = make_expr(prev().str(), name_scope()); @@ -949,7 +950,7 @@ void Compiler::compile_stmt() { is_typed_name = true; if(ctx()->is_compiling_class) { - NameExpr* ne = static_cast(ctx()->s_expr.back().get()); + NameExpr* ne = static_cast(ctx()->s_expr.back()); ctx()->emit_(OP_ADD_CLASS_ANNOTATION, ne->name.index, BC_KEEPLINE); } } @@ -964,8 +965,7 @@ void Compiler::compile_stmt() { ctx()->emit_(OP_POP_TOP, BC_NOARG, BC_KEEPLINE); } } else { - assert(ctx()->s_expr.size() == 1); - ctx()->s_expr.pop_back(); + ctx()->emit_expr(false); } } consume_end_stmt(); @@ -975,7 +975,7 @@ void Compiler::compile_stmt() { void Compiler::consume_type_hints() { EXPR(); - ctx()->s_expr.pop_back(); + ctx()->emit_expr(false); } void Compiler::_add_decorators(const Expr_vector& decorators) { @@ -993,7 +993,7 @@ void Compiler::_add_decorators(const Expr_vector& decorators) { void Compiler::compile_class(const Expr_vector& decorators) { consume(TK("@id")); int namei = StrName(prev().sv()).index; - Expr_ base = nullptr; + Expr* base = nullptr; if(match(TK("("))) { if(is_expression()) { EXPR(); @@ -1294,7 +1294,7 @@ CodeObject_ Compiler::compile() { return code; } else if(mode() == JSON_MODE) { EXPR(); - Expr_ e = ctx()->s_expr.popx_back(); + Expr* e = ctx()->s_expr.popx_back(); if(!e->is_json_object()) SyntaxError("expect a JSON object, literal or array"); consume(TK("@eof")); e->emit_(ctx()); diff --git a/src/compiler/expr.cpp b/src/compiler/expr.cpp index c3da4efa..7846f96c 100644 --- a/src/compiler/expr.cpp +++ b/src/compiler/expr.cpp @@ -41,10 +41,11 @@ void CodeEmitContext::exit_block() { } // clear the expression stack and generate bytecode -void CodeEmitContext::emit_expr() { +void CodeEmitContext::emit_expr(bool emit) { assert(s_expr.size() == 1); - s_expr.back()->emit_(this); - s_expr.pop_back(); + Expr* e = s_expr.popx_back(); + if(emit) e->emit_(this); + delete_expr(e); } int CodeEmitContext::emit_(Opcode opcode, uint16_t arg, int line, bool is_virtual) { @@ -277,7 +278,7 @@ void NegatedExpr::emit_(CodeEmitContext* ctx) { VM* vm = ctx->vm; // if child is a int of float, do constant folding if(child->is_literal()) { - LiteralExpr* lit = static_cast(child.get()); + LiteralExpr* lit = static_cast(child); if(std::holds_alternative(lit->value)) { i64 _val = -std::get(lit->value); ctx->emit_int(_val, line); @@ -540,13 +541,13 @@ void FStringExpr::emit_(CodeEmitContext* ctx) { } void SubscrExpr::emit_(CodeEmitContext* ctx) { - a->emit_(ctx); - b->emit_(ctx); + lhs->emit_(ctx); + rhs->emit_(ctx); Bytecode last_bc = ctx->co->codes.back(); - if(b->is_name() && last_bc.op == OP_LOAD_FAST) { + if(rhs->is_name() && last_bc.op == OP_LOAD_FAST) { ctx->revert_last_emit_(); ctx->emit_(OP_LOAD_SUBSCR_FAST, last_bc.arg, line); - } else if(b->is_literal() && last_bc.op == OP_LOAD_SMALL_INT) { + } else if(rhs->is_literal() && last_bc.op == OP_LOAD_SMALL_INT) { ctx->revert_last_emit_(); ctx->emit_(OP_LOAD_SUBSCR_SMALL_INT, last_bc.arg, line); } else { @@ -555,10 +556,10 @@ void SubscrExpr::emit_(CodeEmitContext* ctx) { } bool SubscrExpr::emit_store(CodeEmitContext* ctx) { - a->emit_(ctx); - b->emit_(ctx); + lhs->emit_(ctx); + rhs->emit_(ctx); Bytecode last_bc = ctx->co->codes.back(); - if(b->is_name() && last_bc.op == OP_LOAD_FAST) { + if(rhs->is_name() && last_bc.op == OP_LOAD_FAST) { ctx->revert_last_emit_(); ctx->emit_(OP_STORE_SUBSCR_FAST, last_bc.arg, line); } else { @@ -568,8 +569,8 @@ bool SubscrExpr::emit_store(CodeEmitContext* ctx) { } void SubscrExpr::emit_inplace(CodeEmitContext* ctx) { - a->emit_(ctx); - b->emit_(ctx); + lhs->emit_(ctx); + rhs->emit_(ctx); ctx->emit_(OP_DUP_TOP_TWO, BC_NOARG, line); ctx->emit_(OP_LOAD_SUBSCR, BC_NOARG, line); } @@ -582,44 +583,44 @@ bool SubscrExpr::emit_store_inplace(CodeEmitContext* ctx) { } bool SubscrExpr::emit_del(CodeEmitContext* ctx) { - a->emit_(ctx); - b->emit_(ctx); + lhs->emit_(ctx); + rhs->emit_(ctx); ctx->emit_(OP_DELETE_SUBSCR, BC_NOARG, line); return true; } void AttribExpr::emit_(CodeEmitContext* ctx) { - a->emit_(ctx); - ctx->emit_(OP_LOAD_ATTR, b.index, line); + child->emit_(ctx); + ctx->emit_(OP_LOAD_ATTR, name.index, line); } bool AttribExpr::emit_del(CodeEmitContext* ctx) { - a->emit_(ctx); - ctx->emit_(OP_DELETE_ATTR, b.index, line); + child->emit_(ctx); + ctx->emit_(OP_DELETE_ATTR, name.index, line); return true; } bool AttribExpr::emit_store(CodeEmitContext* ctx) { - a->emit_(ctx); - ctx->emit_(OP_STORE_ATTR, b.index, line); + child->emit_(ctx); + ctx->emit_(OP_STORE_ATTR, name.index, line); return true; } void AttribExpr::emit_method(CodeEmitContext* ctx) { - a->emit_(ctx); - ctx->emit_(OP_LOAD_METHOD, b.index, line); + child->emit_(ctx); + ctx->emit_(OP_LOAD_METHOD, name.index, line); } void AttribExpr::emit_inplace(CodeEmitContext* ctx) { - a->emit_(ctx); + child->emit_(ctx); ctx->emit_(OP_DUP_TOP, BC_NOARG, line); - ctx->emit_(OP_LOAD_ATTR, b.index, line); + ctx->emit_(OP_LOAD_ATTR, name.index, line); } bool AttribExpr::emit_store_inplace(CodeEmitContext* ctx) { // [a, val] -> [val, a] ctx->emit_(OP_ROT_TWO, BC_NOARG, line); - ctx->emit_(OP_STORE_ATTR, b.index, line); + ctx->emit_(OP_STORE_ATTR, name.index, line); return true; } @@ -633,7 +634,7 @@ void CallExpr::emit_(CodeEmitContext* ctx) { // if callable is a AttrExpr, we should try to use `fast_call` instead of use `boundmethod` proxy if(callable->is_attrib()) { - auto p = static_cast(callable.get()); + auto p = static_cast(callable); p->emit_method(ctx); // OP_LOAD_METHOD } else { callable->emit_(ctx); @@ -692,7 +693,7 @@ bool BinaryExpr::is_compare() const { void BinaryExpr::_emit_compare(CodeEmitContext* ctx, small_vector_2& jmps) { if(lhs->is_compare()) { - static_cast(lhs.get())->_emit_compare(ctx, jmps); + static_cast(lhs)->_emit_compare(ctx, jmps); } else { lhs->emit_(ctx); // [a] } @@ -717,7 +718,7 @@ void BinaryExpr::emit_(CodeEmitContext* ctx) { small_vector_2 jmps; if(is_compare() && lhs->is_compare()) { // (a < b) < c - static_cast(lhs.get())->_emit_compare(ctx, jmps); + static_cast(lhs)->_emit_compare(ctx, jmps); // [b, RES] } else { // (1 + 2) < c