some optimize

This commit is contained in:
blueloveTH 2024-06-08 13:21:27 +08:00
parent f359d07a02
commit 60e1f77f8d
5 changed files with 172 additions and 184 deletions

View File

@ -254,7 +254,7 @@ struct vector {
_data[_size].~T(); _data[_size].~T();
} }
T popx_back() { [[nodiscard]] T popx_back() {
T retval = std::move(back()); T retval = std::move(back());
pop_back(); pop_back();
return retval; return retval;

View File

@ -61,18 +61,19 @@ class Compiler {
/*************************************************/ /*************************************************/
void EXPR(); void EXPR();
void EXPR_TUPLE(bool allow_slice = false); 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 <typename T, typename... Args> template <typename T, typename... Args>
unique_ptr_128<T> make_expr(Args&&... args) { T* make_expr(Args&&... args) {
static_assert(sizeof(T) <= kPoolExprBlockSize); static_assert(sizeof(T) <= kPoolExprBlockSize);
static_assert(std::is_base_of_v<Expr, T>);
void* p = PoolExpr_alloc(); void* p = PoolExpr_alloc();
unique_ptr_128<T> expr(new (p) T(std::forward<Args>(args)...)); T* expr = new (p) T(std::forward<Args>(args)...);
expr->line = prev().line; expr->line = prev().line;
return expr; return expr;
} }
void consume_comp(unique_ptr_128<CompExpr> ce, Expr_ expr); void consume_comp(CompExpr* ce, Expr* expr);
void exprLiteral(); void exprLiteral();
void exprLong(); void exprLong();

View File

@ -8,75 +8,19 @@ namespace pkpy {
struct CodeEmitContext; struct CodeEmitContext;
struct Expr; struct Expr;
template <typename T> typedef small_vector<Expr*, 4> Expr_vector;
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 <typename U>
unique_ptr_128(unique_ptr_128<U>&& other) : ptr(other.detach()) {}
operator bool () const { return ptr != nullptr; }
template <typename U>
unique_ptr_128& operator= (unique_ptr_128<U>&& 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> Expr_;
typedef small_vector<Expr_, 4> Expr_vector;
template <>
constexpr inline bool is_trivially_relocatable_v<Expr_> = true;
struct Expr { struct Expr {
int line = 0; int line = 0;
virtual ~Expr() = default; virtual ~Expr() = default;
virtual void emit_(CodeEmitContext* ctx) = 0; 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_literal() const { return false; }
virtual bool is_json_object() 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); } [[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 { struct CodeEmitContext {
VM* vm; VM* vm;
FuncDecl_ func; // optional FuncDecl_ func; // optional
CodeObject_ co; // 1 CodeEmitContext <=> 1 CodeObject_ CodeObject_ co; // 1 CodeEmitContext <=> 1 CodeObject_
vector<Expr_> s_expr; vector<Expr*> s_expr;
int level; int level;
vector<StrName> global_names; vector<StrName> global_names;
@ -125,7 +75,7 @@ struct CodeEmitContext {
int get_loop() const; int get_loop() const;
CodeBlock* enter_block(CodeBlockType type); CodeBlock* enter_block(CodeBlockType type);
void exit_block(); 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); int emit_(Opcode opcode, uint16_t arg, int line, bool is_virtual = false);
void revert_last_emit_(); void revert_last_emit_();
int emit_int(i64 value, int line); int emit_int(i64 value, int line);
@ -152,19 +102,33 @@ struct NameExpr : Expr {
bool is_name() const override { return true; } bool is_name() const override { return true; }
}; };
struct InvertExpr : Expr { struct _UnaryExpr : Expr {
Expr_ child; 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; void emit_(CodeEmitContext* ctx) override;
}; };
struct StarredExpr : Expr { struct StarredExpr : _UnaryExpr {
int level; 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; } int star_level() const override { return level; }
@ -172,23 +136,18 @@ struct StarredExpr : Expr {
bool emit_store(CodeEmitContext* ctx) override; bool emit_store(CodeEmitContext* ctx) override;
}; };
struct NotExpr : Expr { struct NotExpr : _UnaryExpr {
Expr_ child; using _UnaryExpr::_UnaryExpr;
NotExpr(Expr_&& child) : child(std::move(child)) {}
void emit_(CodeEmitContext* ctx) override; void emit_(CodeEmitContext* ctx) override;
}; };
struct AndExpr : Expr { struct AndExpr : _BinaryExpr {
Expr_ lhs; using _BinaryExpr::_BinaryExpr;
Expr_ rhs;
void emit_(CodeEmitContext* ctx) override; void emit_(CodeEmitContext* ctx) override;
}; };
struct OrExpr : Expr { struct OrExpr : _BinaryExpr {
Expr_ lhs; using _BinaryExpr::_BinaryExpr;
Expr_ rhs;
void emit_(CodeEmitContext* ctx) override; void emit_(CodeEmitContext* ctx) override;
}; };
@ -240,30 +199,40 @@ struct LiteralExpr : Expr {
bool is_json_object() const override { return true; } bool is_json_object() const override { return true; }
}; };
struct NegatedExpr : Expr { struct NegatedExpr : _UnaryExpr {
Expr_ child; using _UnaryExpr::_UnaryExpr;
NegatedExpr(Expr_&& child) : child(std::move(child)) {}
void emit_(CodeEmitContext* ctx) override; void emit_(CodeEmitContext* ctx) override;
bool is_json_object() const override { return child->is_literal(); } bool is_json_object() const override { return child->is_literal(); }
}; };
struct SliceExpr : Expr { struct SliceExpr : Expr {
Expr_ start; Expr* start = nullptr;
Expr_ stop; Expr* stop = nullptr;
Expr_ step; Expr* step = nullptr;
void emit_(CodeEmitContext* ctx) override; void emit_(CodeEmitContext* ctx) override;
~SliceExpr() {
delete_expr(start);
delete_expr(stop);
delete_expr(step);
}
}; };
struct DictItemExpr : Expr { struct DictItemExpr : Expr {
Expr_ key; // maybe nullptr if it is **kwargs Expr* key; // maybe nullptr if it is **kwargs
Expr_ value; Expr* value;
DictItemExpr(): key(nullptr), value(nullptr) {}
int star_level() const override { return value->star_level(); } int star_level() const override { return value->star_level(); }
void emit_(CodeEmitContext* ctx) override; void emit_(CodeEmitContext* ctx) override;
~DictItemExpr() {
delete_expr(key);
delete_expr(value);
}
}; };
struct SequenceExpr : Expr { struct SequenceExpr : Expr {
@ -278,6 +247,10 @@ struct SequenceExpr : Expr {
item->emit_(ctx); item->emit_(ctx);
ctx->emit_(opcode(), items.size(), line); ctx->emit_(opcode(), items.size(), line);
} }
~SequenceExpr() {
for(Expr* item: items) delete_expr(item);
}
}; };
struct ListExpr : SequenceExpr { struct ListExpr : SequenceExpr {
@ -330,15 +303,22 @@ struct TupleExpr : SequenceExpr {
}; };
struct CompExpr : Expr { struct CompExpr : Expr {
Expr_ expr; // loop expr Expr* expr = nullptr; // loop expr
Expr_ vars; // loop vars Expr* vars = nullptr; // loop vars
Expr_ iter; // loop iter Expr* iter = nullptr; // loop iter
Expr_ cond; // optional if condition Expr* cond = nullptr; // optional if condition
virtual Opcode op0() = 0; virtual Opcode op0() = 0;
virtual Opcode op1() = 0; virtual Opcode op1() = 0;
void emit_(CodeEmitContext* ctx) override; void emit_(CodeEmitContext* ctx) override;
~CompExpr() {
delete_expr(expr);
delete_expr(vars);
delete_expr(iter);
delete_expr(cond);
}
}; };
struct ListCompExpr : CompExpr { struct ListCompExpr : CompExpr {
@ -379,10 +359,8 @@ struct FStringExpr : Expr {
void emit_(CodeEmitContext* ctx) override; void emit_(CodeEmitContext* ctx) override;
}; };
struct SubscrExpr : Expr { struct SubscrExpr : _BinaryExpr {
Expr_ a; using _BinaryExpr::_BinaryExpr;
Expr_ b;
bool is_subscr() const override { return true; } bool is_subscr() const override { return true; }
void emit_(CodeEmitContext* ctx) override; void emit_(CodeEmitContext* ctx) override;
@ -393,11 +371,10 @@ struct SubscrExpr : Expr {
bool emit_store_inplace(CodeEmitContext* ctx) override; bool emit_store_inplace(CodeEmitContext* ctx) override;
}; };
struct AttribExpr : Expr { struct AttribExpr : _UnaryExpr {
Expr_ a; StrName name;
StrName b;
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; void emit_(CodeEmitContext* ctx) override;
bool emit_del(CodeEmitContext* ctx) override; bool emit_del(CodeEmitContext* ctx) override;
@ -411,32 +388,34 @@ struct AttribExpr : Expr {
}; };
struct CallExpr : Expr { struct CallExpr : Expr {
Expr_ callable; Expr* callable;
Expr_vector args; Expr_vector args;
// **a will be interpreted as a special keyword argument: {"**": a} // **a will be interpreted as a special keyword argument: {"**": a}
vector<std::pair<Str, Expr_>> kwargs; vector<std::pair<StrName, Expr*>> kwargs;
void emit_(CodeEmitContext* ctx) override; 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 { struct GroupedExpr : _UnaryExpr {
Expr_ a; 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_store(CodeEmitContext* ctx) override { return child->emit_store(ctx); }
bool emit_del(CodeEmitContext* ctx) override { return a->emit_del(ctx); }
bool emit_store(CodeEmitContext* ctx) override { return a->emit_store(ctx); }
}; };
struct BinaryExpr : Expr { struct BinaryExpr : _BinaryExpr {
TokenIndex op; TokenIndex op;
Expr_ lhs;
Expr_ rhs;
bool inplace; bool inplace;
BinaryExpr(bool inplace = false) : inplace(inplace) {} BinaryExpr(TokenIndex op, bool inplace = false)
: _BinaryExpr(), op(op), inplace(inplace) {}
bool is_compare() const override; bool is_compare() const override;
void _emit_compare(CodeEmitContext*, small_vector_2<int, 8>&); void _emit_compare(CodeEmitContext*, small_vector_2<int, 8>&);
@ -444,10 +423,17 @@ struct BinaryExpr : Expr {
}; };
struct TernaryExpr : Expr { struct TernaryExpr : Expr {
Expr_ cond; Expr* cond = nullptr;
Expr_ true_expr; Expr* true_expr = nullptr;
Expr_ false_expr; Expr* false_expr = nullptr;
void emit_(CodeEmitContext* ctx) override; void emit_(CodeEmitContext* ctx) override;
~TernaryExpr() {
delete_expr(cond);
delete_expr(true_expr);
delete_expr(false_expr);
}
}; };
} // namespace pkpy } // namespace pkpy

View File

@ -31,7 +31,7 @@ FuncDecl_ Compiler::push_f_context(Str name) {
} }
void Compiler::pop_context() { 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 // add a `return None` in the end as a guard
// previously, we only do this if the last opcode is not a return // 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 // 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` // special case for `for loop` and `comp`
Expr_ Compiler::EXPR_VARS() { Expr* Compiler::EXPR_VARS() {
Expr_vector items; Expr_vector items;
do { do {
consume(TK("@id")); consume(TK("@id"));
@ -276,8 +276,7 @@ void Compiler::exprTernary() {
} }
void Compiler::exprBinaryOp() { void Compiler::exprBinaryOp() {
auto e = make_expr<BinaryExpr>(); auto e = make_expr<BinaryExpr>(prev().type);
e->op = prev().type;
e->lhs = ctx()->s_expr.popx_back(); e->lhs = ctx()->s_expr.popx_back();
parse_expression(rules[e->op].precedence + 1); parse_expression(rules[e->op].precedence + 1);
e->rhs = ctx()->s_expr.popx_back(); e->rhs = ctx()->s_expr.popx_back();
@ -286,17 +285,19 @@ void Compiler::exprBinaryOp() {
void Compiler::exprNot() { void Compiler::exprNot() {
parse_expression(PREC_LOGICAL_NOT + 1); parse_expression(PREC_LOGICAL_NOT + 1);
ctx()->s_expr.push_back(make_expr<NotExpr>(ctx()->s_expr.popx_back())); NotExpr* e = make_expr<NotExpr>(ctx()->s_expr.popx_back());
ctx()->s_expr.push_back(e);
} }
void Compiler::exprUnaryOp() { void Compiler::exprUnaryOp() {
TokenIndex op = prev().type; TokenIndex op = prev().type;
parse_expression(PREC_UNARY + 1); parse_expression(PREC_UNARY + 1);
vector<Expr*>& s_expr = ctx()->s_expr;
switch(op) { switch(op) {
case TK("-"): ctx()->s_expr.push_back(make_expr<NegatedExpr>(ctx()->s_expr.popx_back())); break; case TK("-"): s_expr.push_back(make_expr<NegatedExpr>(s_expr.popx_back())); break;
case TK("~"): ctx()->s_expr.push_back(make_expr<InvertExpr>(ctx()->s_expr.popx_back())); break; case TK("~"): s_expr.push_back(make_expr<InvertExpr>(s_expr.popx_back())); break;
case TK("*"): ctx()->s_expr.push_back(make_expr<StarredExpr>(1, ctx()->s_expr.popx_back())); break; case TK("*"): s_expr.push_back(make_expr<StarredExpr>(s_expr.popx_back(), 1)); break;
case TK("**"): ctx()->s_expr.push_back(make_expr<StarredExpr>(2, ctx()->s_expr.popx_back())); break; case TK("**"): s_expr.push_back(make_expr<StarredExpr>(s_expr.popx_back(), 2)); break;
default: assert(false); default: assert(false);
} }
} }
@ -307,11 +308,11 @@ void Compiler::exprGroup() {
match_newlines_repl(); match_newlines_repl();
consume(TK(")")); consume(TK(")"));
if(ctx()->s_expr.back()->is_tuple()) return; if(ctx()->s_expr.back()->is_tuple()) return;
Expr_ g = make_expr<GroupedExpr>(ctx()->s_expr.popx_back()); Expr* g = make_expr<GroupedExpr>(ctx()->s_expr.popx_back());
ctx()->s_expr.push_back(std::move(g)); ctx()->s_expr.push_back(std::move(g));
} }
void Compiler::consume_comp(unique_ptr_128<CompExpr> ce, Expr_ expr) { void Compiler::consume_comp(CompExpr* ce, Expr* expr) {
ce->expr = std::move(expr); ce->expr = std::move(expr);
ce->vars = EXPR_VARS(); ce->vars = EXPR_VARS();
consume(TK("in")); consume(TK("in"));
@ -358,7 +359,7 @@ void Compiler::exprMap() {
int star_level = ctx()->s_expr.back()->star_level(); int star_level = ctx()->s_expr.back()->star_level();
if(star_level == 2 || curr().type == TK(":")) { parsing_dict = true; } if(star_level == 2 || curr().type == TK(":")) { parsing_dict = true; }
if(parsing_dict) { if(parsing_dict) {
auto dict_item = make_expr<DictItemExpr>(); DictItemExpr* dict_item = make_expr<DictItemExpr>();
if(star_level == 2) { if(star_level == 2) {
dict_item->key = nullptr; dict_item->key = nullptr;
dict_item->value = ctx()->s_expr.popx_back(); dict_item->value = ctx()->s_expr.popx_back();
@ -401,7 +402,7 @@ void Compiler::exprCall() {
if(curr().type == TK(")")) break; if(curr().type == TK(")")) break;
if(curr().type == TK("@id") && next().type == TK("=")) { if(curr().type == TK("@id") && next().type == TK("=")) {
consume(TK("@id")); consume(TK("@id"));
Str key = prev().str(); StrName key(prev().sv());
consume(TK("=")); consume(TK("="));
EXPR(); EXPR();
e->kwargs.push_back({key, ctx()->s_expr.popx_back()}); e->kwargs.push_back({key, ctx()->s_expr.popx_back()});
@ -476,9 +477,9 @@ void Compiler::exprSlice1() {
void Compiler::exprSubscr() { void Compiler::exprSubscr() {
auto e = make_expr<SubscrExpr>(); auto e = make_expr<SubscrExpr>();
match_newlines_repl(); match_newlines_repl();
e->a = ctx()->s_expr.popx_back(); // a e->lhs = ctx()->s_expr.popx_back(); // a
EXPR_TUPLE(true); EXPR_TUPLE(true);
e->b = ctx()->s_expr.popx_back(); // a[<expr>] e->rhs = ctx()->s_expr.popx_back(); // a[<expr>]
match_newlines_repl(); match_newlines_repl();
consume(TK("]")); consume(TK("]"));
ctx()->s_expr.push_back(std::move(e)); ctx()->s_expr.push_back(std::move(e));
@ -650,7 +651,7 @@ void Compiler::compile_while_loop() {
} }
void Compiler::compile_for_loop() { void Compiler::compile_for_loop() {
Expr_ vars = EXPR_VARS(); Expr* vars = EXPR_VARS();
consume(TK("in")); consume(TK("in"));
EXPR_TUPLE(); EXPR_TUPLE();
ctx()->emit_expr(); ctx()->emit_expr();
@ -764,14 +765,14 @@ bool Compiler::try_compile_assignment() {
case TK("&="): case TK("&="):
case TK("|="): 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(lhs_p->is_starred()) SyntaxError();
if(ctx()->is_compiling_class) SyntaxError("can't use inplace operator in class definition"); if(ctx()->is_compiling_class) SyntaxError("can't use inplace operator in class definition");
advance(); advance();
// a[x] += 1; a and x should be evaluated only once // a[x] += 1; a and x should be evaluated only once
// a.x += 1; a should be evaluated only once // a.x += 1; a should be evaluated only once
auto e = make_expr<BinaryExpr>(true); // inplace=true // -1 to remove =; inplace=true
e->op = prev().type - 1; // -1 to remove = auto e = make_expr<BinaryExpr>(prev().type - 1, true);
e->lhs = ctx()->s_expr.popx_back(); e->lhs = ctx()->s_expr.popx_back();
EXPR_TUPLE(); EXPR_TUPLE();
e->rhs = ctx()->s_expr.popx_back(); e->rhs = ctx()->s_expr.popx_back();
@ -788,7 +789,7 @@ bool Compiler::try_compile_assignment() {
n += 1; n += 1;
} }
// stack size is n+1 // stack size is n+1
Expr_ val = ctx()->s_expr.popx_back(); Expr* val = ctx()->s_expr.popx_back();
val->emit_(ctx()); val->emit_(ctx());
for(int j = 1; j < n; j++) for(int j = 1; j < n; j++)
ctx()->emit_(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE); ctx()->emit_(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
@ -894,7 +895,7 @@ void Compiler::compile_stmt() {
} break; } break;
case TK("del"): { case TK("del"): {
EXPR_TUPLE(); EXPR_TUPLE();
Expr_ e = ctx()->s_expr.popx_back(); Expr* e = ctx()->s_expr.popx_back();
bool ok = e->emit_del(ctx()); bool ok = e->emit_del(ctx());
if(!ok) SyntaxError(); if(!ok) SyntaxError();
consume_end_stmt(); consume_end_stmt();
@ -903,7 +904,7 @@ void Compiler::compile_stmt() {
EXPR(); // [ <expr> ] EXPR(); // [ <expr> ]
ctx()->emit_expr(); ctx()->emit_expr();
ctx()->enter_block(CodeBlockType::CONTEXT_MANAGER); ctx()->enter_block(CodeBlockType::CONTEXT_MANAGER);
Expr_ as_name; Expr* as_name = nullptr;;
if(match(TK("as"))) { if(match(TK("as"))) {
consume(TK("@id")); consume(TK("@id"));
as_name = make_expr<NameExpr>(prev().str(), name_scope()); as_name = make_expr<NameExpr>(prev().str(), name_scope());
@ -949,7 +950,7 @@ void Compiler::compile_stmt() {
is_typed_name = true; is_typed_name = true;
if(ctx()->is_compiling_class) { if(ctx()->is_compiling_class) {
NameExpr* ne = static_cast<NameExpr*>(ctx()->s_expr.back().get()); NameExpr* ne = static_cast<NameExpr*>(ctx()->s_expr.back());
ctx()->emit_(OP_ADD_CLASS_ANNOTATION, ne->name.index, BC_KEEPLINE); 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); ctx()->emit_(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
} }
} else { } else {
assert(ctx()->s_expr.size() == 1); ctx()->emit_expr(false);
ctx()->s_expr.pop_back();
} }
} }
consume_end_stmt(); consume_end_stmt();
@ -975,7 +975,7 @@ void Compiler::compile_stmt() {
void Compiler::consume_type_hints() { void Compiler::consume_type_hints() {
EXPR(); EXPR();
ctx()->s_expr.pop_back(); ctx()->emit_expr(false);
} }
void Compiler::_add_decorators(const Expr_vector& decorators) { 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) { void Compiler::compile_class(const Expr_vector& decorators) {
consume(TK("@id")); consume(TK("@id"));
int namei = StrName(prev().sv()).index; int namei = StrName(prev().sv()).index;
Expr_ base = nullptr; Expr* base = nullptr;
if(match(TK("("))) { if(match(TK("("))) {
if(is_expression()) { if(is_expression()) {
EXPR(); EXPR();
@ -1294,7 +1294,7 @@ CodeObject_ Compiler::compile() {
return code; return code;
} else if(mode() == JSON_MODE) { } else if(mode() == JSON_MODE) {
EXPR(); 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"); if(!e->is_json_object()) SyntaxError("expect a JSON object, literal or array");
consume(TK("@eof")); consume(TK("@eof"));
e->emit_(ctx()); e->emit_(ctx());

View File

@ -41,10 +41,11 @@ void CodeEmitContext::exit_block() {
} }
// clear the expression stack and generate bytecode // clear the expression stack and generate bytecode
void CodeEmitContext::emit_expr() { void CodeEmitContext::emit_expr(bool emit) {
assert(s_expr.size() == 1); assert(s_expr.size() == 1);
s_expr.back()->emit_(this); Expr* e = s_expr.popx_back();
s_expr.pop_back(); if(emit) e->emit_(this);
delete_expr(e);
} }
int CodeEmitContext::emit_(Opcode opcode, uint16_t arg, int line, bool is_virtual) { 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; VM* vm = ctx->vm;
// if child is a int of float, do constant folding // if child is a int of float, do constant folding
if(child->is_literal()) { if(child->is_literal()) {
LiteralExpr* lit = static_cast<LiteralExpr*>(child.get()); LiteralExpr* lit = static_cast<LiteralExpr*>(child);
if(std::holds_alternative<i64>(lit->value)) { if(std::holds_alternative<i64>(lit->value)) {
i64 _val = -std::get<i64>(lit->value); i64 _val = -std::get<i64>(lit->value);
ctx->emit_int(_val, line); ctx->emit_int(_val, line);
@ -540,13 +541,13 @@ void FStringExpr::emit_(CodeEmitContext* ctx) {
} }
void SubscrExpr::emit_(CodeEmitContext* ctx) { void SubscrExpr::emit_(CodeEmitContext* ctx) {
a->emit_(ctx); lhs->emit_(ctx);
b->emit_(ctx); rhs->emit_(ctx);
Bytecode last_bc = ctx->co->codes.back(); 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->revert_last_emit_();
ctx->emit_(OP_LOAD_SUBSCR_FAST, last_bc.arg, line); 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->revert_last_emit_();
ctx->emit_(OP_LOAD_SUBSCR_SMALL_INT, last_bc.arg, line); ctx->emit_(OP_LOAD_SUBSCR_SMALL_INT, last_bc.arg, line);
} else { } else {
@ -555,10 +556,10 @@ void SubscrExpr::emit_(CodeEmitContext* ctx) {
} }
bool SubscrExpr::emit_store(CodeEmitContext* ctx) { bool SubscrExpr::emit_store(CodeEmitContext* ctx) {
a->emit_(ctx); lhs->emit_(ctx);
b->emit_(ctx); rhs->emit_(ctx);
Bytecode last_bc = ctx->co->codes.back(); 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->revert_last_emit_();
ctx->emit_(OP_STORE_SUBSCR_FAST, last_bc.arg, line); ctx->emit_(OP_STORE_SUBSCR_FAST, last_bc.arg, line);
} else { } else {
@ -568,8 +569,8 @@ bool SubscrExpr::emit_store(CodeEmitContext* ctx) {
} }
void SubscrExpr::emit_inplace(CodeEmitContext* ctx) { void SubscrExpr::emit_inplace(CodeEmitContext* ctx) {
a->emit_(ctx); lhs->emit_(ctx);
b->emit_(ctx); rhs->emit_(ctx);
ctx->emit_(OP_DUP_TOP_TWO, BC_NOARG, line); ctx->emit_(OP_DUP_TOP_TWO, BC_NOARG, line);
ctx->emit_(OP_LOAD_SUBSCR, 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) { bool SubscrExpr::emit_del(CodeEmitContext* ctx) {
a->emit_(ctx); lhs->emit_(ctx);
b->emit_(ctx); rhs->emit_(ctx);
ctx->emit_(OP_DELETE_SUBSCR, BC_NOARG, line); ctx->emit_(OP_DELETE_SUBSCR, BC_NOARG, line);
return true; return true;
} }
void AttribExpr::emit_(CodeEmitContext* ctx) { void AttribExpr::emit_(CodeEmitContext* ctx) {
a->emit_(ctx); child->emit_(ctx);
ctx->emit_(OP_LOAD_ATTR, b.index, line); ctx->emit_(OP_LOAD_ATTR, name.index, line);
} }
bool AttribExpr::emit_del(CodeEmitContext* ctx) { bool AttribExpr::emit_del(CodeEmitContext* ctx) {
a->emit_(ctx); child->emit_(ctx);
ctx->emit_(OP_DELETE_ATTR, b.index, line); ctx->emit_(OP_DELETE_ATTR, name.index, line);
return true; return true;
} }
bool AttribExpr::emit_store(CodeEmitContext* ctx) { bool AttribExpr::emit_store(CodeEmitContext* ctx) {
a->emit_(ctx); child->emit_(ctx);
ctx->emit_(OP_STORE_ATTR, b.index, line); ctx->emit_(OP_STORE_ATTR, name.index, line);
return true; return true;
} }
void AttribExpr::emit_method(CodeEmitContext* ctx) { void AttribExpr::emit_method(CodeEmitContext* ctx) {
a->emit_(ctx); child->emit_(ctx);
ctx->emit_(OP_LOAD_METHOD, b.index, line); ctx->emit_(OP_LOAD_METHOD, name.index, line);
} }
void AttribExpr::emit_inplace(CodeEmitContext* ctx) { void AttribExpr::emit_inplace(CodeEmitContext* ctx) {
a->emit_(ctx); child->emit_(ctx);
ctx->emit_(OP_DUP_TOP, BC_NOARG, line); 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) { bool AttribExpr::emit_store_inplace(CodeEmitContext* ctx) {
// [a, val] -> [val, a] // [a, val] -> [val, a]
ctx->emit_(OP_ROT_TWO, BC_NOARG, line); 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; 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 a AttrExpr, we should try to use `fast_call` instead of use `boundmethod` proxy
if(callable->is_attrib()) { if(callable->is_attrib()) {
auto p = static_cast<AttribExpr*>(callable.get()); auto p = static_cast<AttribExpr*>(callable);
p->emit_method(ctx); // OP_LOAD_METHOD p->emit_method(ctx); // OP_LOAD_METHOD
} else { } else {
callable->emit_(ctx); callable->emit_(ctx);
@ -692,7 +693,7 @@ bool BinaryExpr::is_compare() const {
void BinaryExpr::_emit_compare(CodeEmitContext* ctx, small_vector_2<int, 8>& jmps) { void BinaryExpr::_emit_compare(CodeEmitContext* ctx, small_vector_2<int, 8>& jmps) {
if(lhs->is_compare()) { if(lhs->is_compare()) {
static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps); static_cast<BinaryExpr*>(lhs)->_emit_compare(ctx, jmps);
} else { } else {
lhs->emit_(ctx); // [a] lhs->emit_(ctx); // [a]
} }
@ -717,7 +718,7 @@ void BinaryExpr::emit_(CodeEmitContext* ctx) {
small_vector_2<int, 8> jmps; small_vector_2<int, 8> jmps;
if(is_compare() && lhs->is_compare()) { if(is_compare() && lhs->is_compare()) {
// (a < b) < c // (a < b) < c
static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps); static_cast<BinaryExpr*>(lhs)->_emit_compare(ctx, jmps);
// [b, RES] // [b, RES]
} else { } else {
// (1 + 2) < c // (1 + 2) < c