mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-23 13:00:17 +00:00
some optimize
This commit is contained in:
parent
f359d07a02
commit
60e1f77f8d
@ -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;
|
||||
|
@ -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 <typename T, typename... Args>
|
||||
unique_ptr_128<T> make_expr(Args&&... args) {
|
||||
T* make_expr(Args&&... args) {
|
||||
static_assert(sizeof(T) <= kPoolExprBlockSize);
|
||||
static_assert(std::is_base_of_v<Expr, T>);
|
||||
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;
|
||||
return expr;
|
||||
}
|
||||
|
||||
void consume_comp(unique_ptr_128<CompExpr> ce, Expr_ expr);
|
||||
void consume_comp(CompExpr* ce, Expr* expr);
|
||||
|
||||
void exprLiteral();
|
||||
void exprLong();
|
||||
|
@ -8,75 +8,19 @@ namespace pkpy {
|
||||
struct CodeEmitContext;
|
||||
struct Expr;
|
||||
|
||||
template <typename T>
|
||||
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;
|
||||
typedef small_vector<Expr*, 4> 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<Expr_> s_expr;
|
||||
vector<Expr*> s_expr;
|
||||
int level;
|
||||
vector<StrName> 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<std::pair<Str, Expr_>> kwargs;
|
||||
vector<std::pair<StrName, Expr*>> 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<int, 8>&);
|
||||
@ -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
|
||||
|
@ -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<BinaryExpr>();
|
||||
e->op = prev().type;
|
||||
auto e = make_expr<BinaryExpr>(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<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() {
|
||||
TokenIndex op = prev().type;
|
||||
parse_expression(PREC_UNARY + 1);
|
||||
vector<Expr*>& s_expr = ctx()->s_expr;
|
||||
switch(op) {
|
||||
case TK("-"): ctx()->s_expr.push_back(make_expr<NegatedExpr>(ctx()->s_expr.popx_back())); break;
|
||||
case TK("~"): ctx()->s_expr.push_back(make_expr<InvertExpr>(ctx()->s_expr.popx_back())); break;
|
||||
case TK("*"): ctx()->s_expr.push_back(make_expr<StarredExpr>(1, ctx()->s_expr.popx_back())); 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<NegatedExpr>(s_expr.popx_back())); break;
|
||||
case TK("~"): s_expr.push_back(make_expr<InvertExpr>(s_expr.popx_back())); break;
|
||||
case TK("*"): s_expr.push_back(make_expr<StarredExpr>(s_expr.popx_back(), 1)); break;
|
||||
case TK("**"): s_expr.push_back(make_expr<StarredExpr>(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<GroupedExpr>(ctx()->s_expr.popx_back());
|
||||
Expr* g = make_expr<GroupedExpr>(ctx()->s_expr.popx_back());
|
||||
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->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>();
|
||||
DictItemExpr* dict_item = make_expr<DictItemExpr>();
|
||||
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<SubscrExpr>();
|
||||
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[<expr>]
|
||||
e->rhs = ctx()->s_expr.popx_back(); // a[<expr>]
|
||||
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<BinaryExpr>(true); // inplace=true
|
||||
e->op = prev().type - 1; // -1 to remove =
|
||||
// -1 to remove =; inplace=true
|
||||
auto e = make_expr<BinaryExpr>(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(); // [ <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<NameExpr>(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<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);
|
||||
}
|
||||
}
|
||||
@ -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());
|
||||
|
@ -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<LiteralExpr*>(child.get());
|
||||
LiteralExpr* lit = static_cast<LiteralExpr*>(child);
|
||||
if(std::holds_alternative<i64>(lit->value)) {
|
||||
i64 _val = -std::get<i64>(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<AttribExpr*>(callable.get());
|
||||
auto p = static_cast<AttribExpr*>(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<int, 8>& jmps) {
|
||||
if(lhs->is_compare()) {
|
||||
static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
|
||||
static_cast<BinaryExpr*>(lhs)->_emit_compare(ctx, jmps);
|
||||
} else {
|
||||
lhs->emit_(ctx); // [a]
|
||||
}
|
||||
@ -717,7 +718,7 @@ void BinaryExpr::emit_(CodeEmitContext* ctx) {
|
||||
small_vector_2<int, 8> jmps;
|
||||
if(is_compare() && lhs->is_compare()) {
|
||||
// (a < b) < c
|
||||
static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
|
||||
static_cast<BinaryExpr*>(lhs)->_emit_compare(ctx, jmps);
|
||||
// [b, RES]
|
||||
} else {
|
||||
// (1 + 2) < c
|
||||
|
Loading…
x
Reference in New Issue
Block a user