This commit is contained in:
blueloveTH 2023-04-02 14:14:41 +08:00
parent b88cd66046
commit 449fb9a2f8
7 changed files with 295 additions and 165 deletions

View File

@ -26,49 +26,86 @@ inline PyObject* VM::run_frame(Frame* frame){
Function& f = CAST(Function&, frame->top()); // reference Function& f = CAST(Function&, frame->top()); // reference
f._closure = frame->_locals; f._closure = frame->_locals;
} continue; } continue;
case OP_LOAD_NAME_REF: {
frame->push(PyRef(NameRef(frame->co->names[byte.arg])));
} continue;
case OP_LOAD_NAME: {
frame->push(NameRef(frame->co->names[byte.arg]).get(this, frame));
} continue;
case OP_STORE_NAME: {
auto& p = frame->co->names[byte.arg];
NameRef(p).set(this, frame, frame->pop());
} continue;
case OP_BUILD_ATTR_REF: case OP_BUILD_ATTR: {
auto& attr = frame->co->names[byte.arg];
PyObject* obj = frame->pop_value(this);
AttrRef ref = AttrRef(obj, NameRef(attr));
if(byte.op == OP_BUILD_ATTR) frame->push(ref.get(this, frame));
else frame->push(PyRef(ref));
} continue;
case OP_BUILD_INDEX: {
PyObject* index = frame->pop_value(this);
auto ref = IndexRef(frame->pop_value(this), index);
if(byte.arg > 0) frame->push(ref.get(this, frame));
else frame->push(PyRef(ref));
} continue;
case OP_FAST_INDEX: case OP_FAST_INDEX_REF: {
auto& a = frame->co->names[byte.arg & 0xFFFF];
auto& x = frame->co->names[(byte.arg >> 16) & 0xFFFF];
auto ref = IndexRef(NameRef(a).get(this, frame), NameRef(x).get(this, frame));
if(byte.op == OP_FAST_INDEX) frame->push(ref.get(this, frame));
else frame->push(PyRef(ref));
} continue;
case OP_ROT_TWO: ::std::swap(frame->top(), frame->top_1()); continue; case OP_ROT_TWO: ::std::swap(frame->top(), frame->top_1()); continue;
case OP_STORE_REF: {
PyRef_AS_C(frame->top_1())->set(this, frame, frame->top_value(this));
frame->_pop(); frame->_pop();
} continue;
case OP_DELETE_REF:
PyRef_AS_C(frame->top())->del(this, frame);
frame->_pop();
continue;
case OP_BUILD_TUPLE: { case OP_BUILD_TUPLE: {
Args items = frame->pop_n_values_reversed(this, byte.arg); Args items = frame->pop_n_values_reversed(this, byte.arg);
frame->push(VAR(std::move(items))); frame->push(VAR(std::move(items)));
} continue; } continue;
/*****************************************/
case OP_LOAD_NAME: {
// TODO: use name resolution linked list to optimize this
StrName name = frame->co->names[byte.arg];
PyObject* val;
val = frame->f_locals().try_get(name);
if(val != nullptr) { frame->push(val); continue; }
val = frame->f_closure_try_get(name);
if(val != nullptr) { frame->push(val); continue; }
val = frame->f_globals().try_get(name);
if(val != nullptr) { frame->push(val); continue; }
val = vm->builtins->attr().try_get(name);
if(val != nullptr) { frame->push(val); continue; }
vm->NameError(name);
} continue;
case OP_LOAD_ATTR: {
PyObject* a = frame->top();
StrName name = frame->co->names[byte.arg];
frame->top() = getattr(a, name);
} continue;
case OP_LOAD_SUBSCR: {
PyObject* b = frame->popx();
PyObject* a = frame->top();
frame->top() = fast_call(__getitem__, Args{a, b});
} continue;
case OP_STORE_LOCAL: {
StrName name = frame->co->names[byte.arg];
frame->f_locals().set(name, frame->popx());
} continue;
case OP_STORE_GLOBAL: {
StrName name = frame->co->names[byte.arg];
frame->f_globals().set(name, frame->popx());
} continue;
case OP_STORE_ATTR: {
StrName name = frame->co->names[byte.arg];
PyObject* a = frame->popx();
PyObject* val = frame->popx();
setattr(a, name, val);
} continue;
case OP_STORE_SUBSCR: {
Args args(3);
args[1] = frame->popx(); // b
args[0] = frame->popx(); // a
args[2] = frame->popx(); // val
fast_call(__setitem__, std::move(args));
} continue;
case OP_DELETE_LOCAL: {
StrName name = frame->co->names[byte.arg];
if(frame->f_locals().contains(name)){
frame->f_locals().erase(name);
}else{
NameError(name);
}
} continue;
case OP_DELETE_GLOBAL: {
StrName name = frame->co->names[byte.arg];
if(frame->f_globals().contains(name)){
frame->f_globals().erase(name);
}else{
NameError(name);
}
} continue;
case OP_DELETE_ATTR: {
PyObject* a = frame->popx();
StrName name = frame->co->names[byte.arg];
if(!a->is_attr_valid()) TypeError("cannot delete attribute");
if(!a->attr().contains(name)) AttributeError(a, name);
a->attr().erase(name);
} continue;
case OP_DELETE_SUBSCR: {
PyObject* b = frame->popx();
PyObject* a = frame->popx();
fast_call(__delitem__, Args{a, b});
} continue;
/*****************************************/
case OP_BUILD_TUPLE_REF: { case OP_BUILD_TUPLE_REF: {
Args items = frame->pop_n_reversed(byte.arg); Args items = frame->pop_n_reversed(byte.arg);
frame->push(PyRef(TupleRef(std::move(items)))); frame->push(PyRef(TupleRef(std::move(items))));

View File

@ -25,7 +25,7 @@ inline const char* OP_NAMES[] = {
}; };
struct Bytecode{ struct Bytecode{
uint8_t op; uint16_t op;
uint16_t block; uint16_t block;
int arg; int arg;
int line; int line;
@ -61,7 +61,7 @@ struct CodeObject {
std::vector<Bytecode> codes; std::vector<Bytecode> codes;
List consts; List consts;
std::vector<std::pair<StrName, NameScope>> names; std::vector<StrName> names;
std::set<StrName> global_names; std::set<StrName> global_names;
std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} }; std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
std::map<StrName, int> labels; std::map<StrName, int> labels;

View File

@ -173,7 +173,7 @@ private:
} }
template <typename T, typename... Args> template <typename T, typename... Args>
std::unique_ptr<T> expr_prev_line(Args&&... args) { std::unique_ptr<T> make_expr(Args&&... args) {
std::unique_ptr<T> expr = std::make_unique<T>(std::forward<Args>(args)...); std::unique_ptr<T> expr = std::make_unique<T>(std::forward<Args>(args)...);
expr->line = prev().line; expr->line = prev().line;
return expr; return expr;
@ -183,17 +183,17 @@ private:
// PASS // PASS
void exprLiteral(){ void exprLiteral(){
ctx()->s_expr.push(expr_prev_line<LiteralExpr>(prev().value)); ctx()->s_expr.push(make_expr<LiteralExpr>(prev().value));
} }
// PASS // PASS
void exprFString(){ void exprFString(){
ctx()->s_expr.push(expr_prev_line<FStringExpr>(std::get<Str>(prev().value))); ctx()->s_expr.push(make_expr<FStringExpr>(std::get<Str>(prev().value)));
} }
// PASS // PASS
void exprLambda(){ void exprLambda(){
auto e = expr_prev_line<LambdaExpr>(); auto e = make_expr<LambdaExpr>();
e->func.name = "<lambda>"; e->func.name = "<lambda>";
e->scope = name_scope(); e->scope = name_scope();
if(!match(TK(":"))){ if(!match(TK(":"))){
@ -260,7 +260,7 @@ private:
// PASS // PASS
void exprTuple(){ void exprTuple(){
auto e = expr_prev_line<TupleExpr>(); auto e = make_expr<TupleExpr>();
do { do {
EXPR(); // NOTE: "1," will fail, "1,2" will be ok EXPR(); // NOTE: "1," will fail, "1,2" will be ok
e->items.push_back(ctx()->s_expr.popx()); e->items.push_back(ctx()->s_expr.popx());
@ -270,7 +270,7 @@ private:
// PASS // PASS
void exprOr(){ void exprOr(){
auto e = expr_prev_line<OrExpr>(); auto e = make_expr<OrExpr>();
e->lhs = ctx()->s_expr.popx(); e->lhs = ctx()->s_expr.popx();
parse_expression(PREC_LOGICAL_OR + 1); parse_expression(PREC_LOGICAL_OR + 1);
e->rhs = ctx()->s_expr.popx(); e->rhs = ctx()->s_expr.popx();
@ -279,7 +279,7 @@ private:
// PASS // PASS
void exprAnd(){ void exprAnd(){
auto e = expr_prev_line<AndExpr>(); auto e = make_expr<AndExpr>();
e->lhs = ctx()->s_expr.popx(); e->lhs = ctx()->s_expr.popx();
parse_expression(PREC_LOGICAL_AND + 1); parse_expression(PREC_LOGICAL_AND + 1);
e->rhs = ctx()->s_expr.popx(); e->rhs = ctx()->s_expr.popx();
@ -288,7 +288,7 @@ private:
// PASS // PASS
void exprTernary(){ void exprTernary(){
auto e = expr_prev_line<TernaryExpr>(); auto e = make_expr<TernaryExpr>();
e->cond = ctx()->s_expr.popx(); e->cond = ctx()->s_expr.popx();
EXPR(); // if true EXPR(); // if true
e->true_expr = ctx()->s_expr.popx(); e->true_expr = ctx()->s_expr.popx();
@ -300,7 +300,7 @@ private:
// PASS // PASS
void exprBinaryOp(){ void exprBinaryOp(){
auto e = expr_prev_line<BinaryExpr>(); auto e = make_expr<BinaryExpr>();
e->op = prev().type; e->op = prev().type;
e->lhs = ctx()->s_expr.popx(); e->lhs = ctx()->s_expr.popx();
parse_expression(rules[e->op].precedence + 1); parse_expression(rules[e->op].precedence + 1);
@ -311,7 +311,7 @@ private:
// PASS // PASS
void exprNot() { void exprNot() {
parse_expression(PREC_LOGICAL_NOT + 1); parse_expression(PREC_LOGICAL_NOT + 1);
ctx()->s_expr.push(expr_prev_line<NotExpr>(ctx()->s_expr.popx())); ctx()->s_expr.push(make_expr<NotExpr>(ctx()->s_expr.popx()));
} }
// PASS // PASS
@ -320,10 +320,10 @@ private:
parse_expression(PREC_UNARY + 1); parse_expression(PREC_UNARY + 1);
switch(op){ switch(op){
case TK("-"): case TK("-"):
ctx()->s_expr.push(expr_prev_line<NegatedExpr>(ctx()->s_expr.popx())); ctx()->s_expr.push(make_expr<NegatedExpr>(ctx()->s_expr.popx()));
break; break;
case TK("*"): case TK("*"):
ctx()->s_expr.push(expr_prev_line<StarredExpr>(ctx()->s_expr.popx())); ctx()->s_expr.push(make_expr<StarredExpr>(ctx()->s_expr.popx()));
break; break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
@ -375,7 +375,7 @@ private:
match_newlines(mode()==REPL_MODE); match_newlines(mode()==REPL_MODE);
} while (match(TK(","))); } while (match(TK(",")));
consume(TK("]")); consume(TK("]"));
auto e = expr_prev_line<ListExpr>(std::move(items)); auto e = make_expr<ListExpr>(std::move(items));
e->line = line; // override line e->line = line; // override line
ctx()->s_expr.push(std::move(e)); ctx()->s_expr.push(std::move(e));
} }
@ -392,7 +392,7 @@ private:
if(parsing_dict){ if(parsing_dict){
consume(TK(":")); consume(TK(":"));
EXPR(); EXPR();
auto dict_item = expr_prev_line<DictItemExpr>(); auto dict_item = make_expr<DictItemExpr>();
dict_item->key = ctx()->s_expr.popx(); dict_item->key = ctx()->s_expr.popx();
dict_item->value = ctx()->s_expr.popx(); dict_item->value = ctx()->s_expr.popx();
items.push_back(std::move(dict_item)); items.push_back(std::move(dict_item));
@ -410,17 +410,17 @@ private:
} while (match(TK(","))); } while (match(TK(",")));
consume(TK("}")); consume(TK("}"));
if(items.size()==0 || parsing_dict){ if(items.size()==0 || parsing_dict){
auto e = expr_prev_line<DictExpr>(std::move(items)); auto e = make_expr<DictExpr>(std::move(items));
ctx()->s_expr.push(std::move(e)); ctx()->s_expr.push(std::move(e));
}else{ }else{
auto e = expr_prev_line<SetExpr>(std::move(items)); auto e = make_expr<SetExpr>(std::move(items));
ctx()->s_expr.push(std::move(e)); ctx()->s_expr.push(std::move(e));
} }
} }
// PASS // PASS
void exprCall() { void exprCall() {
auto e = expr_prev_line<CallExpr>(); auto e = make_expr<CallExpr>();
e->callable = ctx()->s_expr.popx(); e->callable = ctx()->s_expr.popx();
do { do {
match_newlines(mode()==REPL_MODE); match_newlines(mode()==REPL_MODE);
@ -434,38 +434,32 @@ private:
} else{ } else{
if(!e->kwargs.empty()) SyntaxError("positional argument follows keyword argument"); if(!e->kwargs.empty()) SyntaxError("positional argument follows keyword argument");
EXPR(); EXPR();
// if(co()->codes.back().op == OP_UNARY_STAR) need_unpack = true;
e->args.push_back(ctx()->s_expr.popx()); e->args.push_back(ctx()->s_expr.popx());
} }
match_newlines(mode()==REPL_MODE); match_newlines(mode()==REPL_MODE);
} while (match(TK(","))); } while (match(TK(",")));
consume(TK(")")); consume(TK(")"));
if(e->args.size() > 32767) SyntaxError("too many positional arguments");
if(e->kwargs.size() > 32767) SyntaxError("too many keyword arguments");
ctx()->s_expr.push(std::move(e)); ctx()->s_expr.push(std::move(e));
// if(ARGC > 32767) SyntaxError("too many positional arguments");
// if(KWARGC > 32767) SyntaxError("too many keyword arguments");
// if(KWARGC > 0){
// emit(need_unpack ? OP_CALL_KWARGS_UNPACK : OP_CALL_KWARGS, (KWARGC << 16) | ARGC);
// }else{
// emit(need_unpack ? OP_CALL_UNPACK : OP_CALL, ARGC);
// }
} }
// PASS // PASS
void exprName(){ void exprName(){
ctx()->s_expr.push(expr_prev_line<NameExpr>(prev().str(), name_scope())); ctx()->s_expr.push(make_expr<NameExpr>(prev().str(), name_scope()));
} }
// PASS // PASS
void exprAttrib() { void exprAttrib() {
consume(TK("@id")); consume(TK("@id"));
ctx()->s_expr.push( ctx()->s_expr.push(
expr_prev_line<AttribExpr>(ctx()->s_expr.popx(), prev().str()) make_expr<AttribExpr>(ctx()->s_expr.popx(), prev().str())
); );
} }
// PASS // PASS
void exprSubscr() { void exprSubscr() {
auto e = expr_prev_line<SubscrExpr>(); auto e = make_expr<SubscrExpr>();
std::vector<Expr_> items; std::vector<Expr_> items;
do { do {
EXPR_TUPLE(); EXPR_TUPLE();
@ -477,7 +471,7 @@ private:
e->b = std::move(items[0]); e->b = std::move(items[0]);
break; break;
case 2: case 3: { case 2: case 3: {
auto slice = expr_prev_line<SliceExpr>(); auto slice = make_expr<SliceExpr>();
slice->start = std::move(items[0]); slice->start = std::move(items[0]);
slice->stop = std::move(items[1]); slice->stop = std::move(items[1]);
if(items.size()==3){ if(items.size()==3){
@ -492,7 +486,7 @@ private:
// PASS // PASS
void exprLiteral0() { void exprLiteral0() {
ctx()->s_expr.push(expr_prev_line<Literal0Expr>(prev().type)); ctx()->s_expr.push(make_expr<Literal0Expr>(prev().type));
} }
void compile_block_body() { void compile_block_body() {
@ -708,15 +702,6 @@ private:
ctx()->emit(OP_ASSERT, BC_NOARG, kw_line); ctx()->emit(OP_ASSERT, BC_NOARG, kw_line);
consume_end_stmt(); consume_end_stmt();
break; break;
case TK("del"):
EXPR_TUPLE();
Expr_ e = ctx()->s_expr.popx();
switch(e->ref_type()){
case EXPR_NAME_REF:
}
ctx()->emit(OP_DELETE_REF, BC_NOARG, kw_line);
consume_end_stmt();
break;
case TK("global"): case TK("global"):
do { do {
consume(TK("@id")); consume(TK("@id"));
@ -735,6 +720,13 @@ private:
ctx()->emit(OP_RAISE, dummy_t, kw_line); ctx()->emit(OP_RAISE, dummy_t, kw_line);
consume_end_stmt(); consume_end_stmt();
} break; } break;
case TK("del"): {
EXPR_TUPLE();
Expr_ e = ctx()->s_expr.popx();
bool ok = e->emit_del(ctx());
if(!ok) SyntaxError();
consume_end_stmt();
} break;
case TK("with"): { case TK("with"): {
EXPR(true); EXPR(true);
consume(TK("as")); consume(TK("as"));

View File

@ -11,25 +11,20 @@ namespace pkpy{
struct CodeEmitContext; struct CodeEmitContext;
enum ExprRefType{
EXPR_NO_REF,
EXPR_NAME_REF,
EXPR_ATTR_REF,
EXPR_INDEX_REF,
EXPR_STARRED_REF,
EXPR_TUPLE_REF
};
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;
virtual Str str() const = 0; virtual Str str() const = 0;
virtual std::vector<const Expr*> children() = 0;
virtual ExprRefType ref_type() const { virtual std::vector<const Expr*> children() const { return {}; }
return EXPR_NO_REF; virtual bool is_starred() const { return false; }
}
// for OP_DELETE_XXX
virtual bool emit_del(CodeEmitContext* ctx) { return false; }
// for OP_STORE_XXX
virtual bool emit_store(CodeEmitContext* ctx) { return false; }
}; };
struct CodeEmitContext{ struct CodeEmitContext{
@ -67,13 +62,12 @@ struct CodeEmitContext{
void emit_expr(){ void emit_expr(){
if(s_expr.size() != 1) UNREACHABLE(); if(s_expr.size() != 1) UNREACHABLE();
Expr_ expr = s_expr.popx(); Expr_ expr = s_expr.popx();
// emit expr->emit(this);
// ...
} }
int emit(Opcode opcode, int arg, int line) { int emit(Opcode opcode, int arg, int line) {
co->codes.push_back( co->codes.push_back(
Bytecode{(uint8_t)opcode, (uint16_t)curr_block_i, arg, line} Bytecode{(uint16_t)opcode, (uint16_t)curr_block_i, arg, line}
); );
int i = co->codes.size() - 1; int i = co->codes.size() - 1;
if(line==BC_KEEPLINE && i>=1) co->codes[i].line = co->codes[i-1].line; if(line==BC_KEEPLINE && i>=1) co->codes[i].line = co->codes[i-1].line;
@ -91,13 +85,11 @@ struct CodeEmitContext{
return true; return true;
} }
int add_name(StrName name, NameScope scope){ int add_name(StrName name){
if(scope == NAME_LOCAL && co->global_names.count(name)) scope = NAME_GLOBAL;
auto p = std::make_pair(name, scope);
for(int i=0; i<co->names.size(); i++){ for(int i=0; i<co->names.size(); i++){
if(co->names[i] == p) return i; if(co->names[i] == name) return i;
} }
co->names.push_back(p); co->names.push_back(name);
return co->names.size() - 1; return co->names.size() - 1;
} }
@ -107,7 +99,7 @@ struct CodeEmitContext{
} }
}; };
// PASS
struct NameExpr: Expr{ struct NameExpr: Expr{
Str name; Str name;
NameScope scope; NameScope scope;
@ -117,59 +109,99 @@ struct NameExpr: Expr{
Str str() const override { return "$" + name; } Str str() const override { return "$" + name; }
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {
int index = ctx->add_name(name, scope); int index = ctx->add_name(name);
ctx->emit(OP_LOAD_NAME, index, line); ctx->emit(OP_LOAD_NAME, index, line);
} }
ExprRefType ref_type() const override { bool emit_del(CodeEmitContext* ctx) override {
return EXPR_NAME_REF; int index = ctx->add_name(name);
switch(scope){
case NAME_LOCAL:
ctx->emit(OP_DELETE_LOCAL, index, line);
break;
case NAME_GLOBAL:
ctx->emit(OP_DELETE_GLOBAL, index, line);
break;
default: UNREACHABLE(); break;
}
return true;
}
bool emit_store(CodeEmitContext* ctx) override {
int index = ctx->add_name(name);
switch(scope){
case NAME_LOCAL:
ctx->emit(OP_STORE_LOCAL, index, line);
break;
case NAME_GLOBAL:
ctx->emit(OP_STORE_GLOBAL, index, line);
break;
default: UNREACHABLE(); break;
}
return true;
} }
}; };
// *号运算符,作为左值和右值效果不同
struct StarredExpr: Expr{ struct StarredExpr: Expr{
Expr_ child; Expr_ child;
StarredExpr(Expr_&& child): child(std::move(child)) {} StarredExpr(Expr_&& child): child(std::move(child)) {}
Str str() const override { return "*"; } Str str() const override { return "*"; }
std::vector<const Expr*> children() const override { return {child.get()}; }
bool is_starred() const override { return true; }
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {
child->emit(ctx); child->emit(ctx);
ctx->emit(OP_UNARY_STAR, (int)false, line); // as a rvalue, we should do unpack here
//ctx->emit(OP_UNARY_STAR, (int)false, line);
} }
ExprRefType ref_type() const override { bool emit_store(CodeEmitContext* ctx) override {
return EXPR_STARRED_REF; child->emit(ctx);
// as a lvalue, we should do pack here
//ctx->emit(OP_UNARY_STAR, (int)true, line);
return true;
} }
}; };
// PASS
struct NegatedExpr: Expr{ struct NegatedExpr: Expr{
Expr_ child; Expr_ child;
NegatedExpr(Expr_&& child): child(std::move(child)) {} NegatedExpr(Expr_&& child): child(std::move(child)) {}
Str str() const override { return "-"; } Str str() const override { return "-"; }
std::vector<const Expr*> children() const override { return {child.get()}; }
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {
child->emit(ctx); child->emit(ctx);
ctx->emit(OP_UNARY_NEGATIVE, BC_NOARG, line); ctx->emit(OP_UNARY_NEGATIVE, BC_NOARG, line);
} }
}; };
// PASS
struct NotExpr: Expr{ struct NotExpr: Expr{
Expr_ child; Expr_ child;
NotExpr(Expr_&& child): child(std::move(child)) {} NotExpr(Expr_&& child): child(std::move(child)) {}
Str str() const override { return "not"; } Str str() const override { return "not"; }
std::vector<const Expr*> children() const override { return {child.get()}; }
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {
child->emit(ctx); child->emit(ctx);
ctx->emit(OP_UNARY_NOT, BC_NOARG, line); ctx->emit(OP_UNARY_NOT, BC_NOARG, line);
} }
}; };
// PASS
struct AndExpr: Expr{ struct AndExpr: Expr{
Expr_ lhs; Expr_ lhs;
Expr_ rhs; Expr_ rhs;
Str str() const override { return "and"; } Str str() const override { return "and"; }
std::vector<const Expr*> children() const override { return {lhs.get(), rhs.get()}; }
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {
lhs->emit(ctx); lhs->emit(ctx);
int patch = ctx->emit(OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, line); int patch = ctx->emit(OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, line);
@ -178,11 +210,14 @@ struct AndExpr: Expr{
} }
}; };
// PASS
struct OrExpr: Expr{ struct OrExpr: Expr{
Expr_ lhs; Expr_ lhs;
Expr_ rhs; Expr_ rhs;
Str str() const override { return "or"; } Str str() const override { return "or"; }
std::vector<const Expr*> children() const override { return {lhs.get(), rhs.get()}; }
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {
lhs->emit(ctx); lhs->emit(ctx);
int patch = ctx->emit(OP_JUMP_IF_TRUE_OR_POP, BC_NOARG, line); int patch = ctx->emit(OP_JUMP_IF_TRUE_OR_POP, BC_NOARG, line);
@ -249,12 +284,18 @@ struct LiteralExpr: Expr{
} }
}; };
// PASS
struct SliceExpr: Expr{ struct SliceExpr: Expr{
Expr_ start; Expr_ start;
Expr_ stop; Expr_ stop;
Expr_ step; Expr_ step;
Str str() const override { return "slice()"; } Str str() const override { return "slice()"; }
std::vector<const Expr*> children() const override {
// may contain nullptr
return {start.get(), stop.get(), step.get()};
}
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {
if(start){ if(start){
start->emit(ctx); start->emit(ctx);
@ -278,11 +319,30 @@ struct SliceExpr: Expr{
} }
}; };
struct DictItemExpr: Expr{
Expr_ key;
Expr_ value;
Str str() const override { return "k:v"; }
std::vector<const Expr*> children() const override { return {key.get(), value.get()}; }
void emit(CodeEmitContext* ctx) override {
key->emit(ctx);
value->emit(ctx);
ctx->emit(OP_BUILD_TUPLE, 2, line);
}
};
struct SequenceExpr: Expr{ struct SequenceExpr: Expr{
std::vector<Expr_> items; std::vector<Expr_> items;
SequenceExpr(std::vector<Expr_>&& items): items(std::move(items)) {} SequenceExpr(std::vector<Expr_>&& items): items(std::move(items)) {}
virtual Opcode opcode() const = 0; virtual Opcode opcode() const = 0;
std::vector<const Expr*> children() const override {
std::vector<const Expr*> ret;
for(auto& item: items) ret.push_back(item.get());
return ret;
}
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {
for(auto& item: items) item->emit(ctx); for(auto& item: items) item->emit(ctx);
ctx->emit(opcode(), items.size(), line); ctx->emit(opcode(), items.size(), line);
@ -308,8 +368,9 @@ struct TupleExpr: SequenceExpr{
Str str() const override { return "tuple()"; } Str str() const override { return "tuple()"; }
Opcode opcode() const override { return OP_BUILD_TUPLE; } Opcode opcode() const override { return OP_BUILD_TUPLE; }
ExprRefType ref_type() const override { bool emit_store(CodeEmitContext* ctx) override {
return EXPR_TUPLE_REF; // ...
return true;
} }
}; };
@ -318,14 +379,6 @@ struct CompExpr: Expr{
Expr_ vars; // loop vars Expr_ vars; // loop vars
Expr_ iter; // loop iter Expr_ iter; // loop iter
Expr_ cond; // optional if condition Expr_ cond; // optional if condition
virtual void emit_expr() = 0;
};
// a:b
struct DictItemExpr: Expr{
Expr_ key;
Expr_ value;
Str str() const override { return "k:v"; }
}; };
struct ListCompExpr: CompExpr{ struct ListCompExpr: CompExpr{
@ -345,7 +398,9 @@ struct LambdaExpr: Expr{
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {
VM* vm = ctx->vm; VM* vm = ctx->vm;
ctx->emit(OP_LOAD_FUNCTION, ctx->add_const(VAR(func)), line); ctx->emit(OP_LOAD_FUNCTION, ctx->add_const(VAR(func)), line);
if(scope == NAME_LOCAL) ctx->emit(OP_SETUP_CLOSURE, BC_NOARG, BC_KEEPLINE); if(scope == NAME_LOCAL){
ctx->emit(OP_SETUP_CLOSURE, BC_NOARG, BC_KEEPLINE);
}
} }
}; };
@ -393,11 +448,21 @@ struct SubscrExpr: Expr{
void emit(CodeEmitContext* ctx) override{ void emit(CodeEmitContext* ctx) override{
a->emit(ctx); a->emit(ctx);
b->emit(ctx); b->emit(ctx);
ctx->emit(OP_BUILD_INDEX, BC_NOARG, line); ctx->emit(OP_LOAD_SUBSCR, BC_NOARG, line);
} }
ExprRefType ref_type() const override { bool emit_del(CodeEmitContext* ctx) override {
return EXPR_INDEX_REF; a->emit(ctx);
b->emit(ctx);
ctx->emit(OP_DELETE_SUBSCR, BC_NOARG, line);
return true;
}
bool emit_store(CodeEmitContext* ctx) override {
a->emit(ctx);
b->emit(ctx);
ctx->emit(OP_STORE_SUBSCR, BC_NOARG, line);
return true;
} }
}; };
@ -408,16 +473,56 @@ struct AttribExpr: Expr{
AttribExpr(Expr_ a, Str&& b): a(std::move(a)), b(std::move(b)) {} AttribExpr(Expr_ a, Str&& b): a(std::move(a)), b(std::move(b)) {}
Str str() const override { return "a.b"; } Str str() const override { return "a.b"; }
ExprRefType ref_type() const override { void emit(CodeEmitContext* ctx) override{
return EXPR_ATTR_REF; a->emit(ctx);
int index = ctx->add_name(b);
ctx->emit(OP_LOAD_ATTR, index, line);
}
bool emit_del(CodeEmitContext* ctx) override {
a->emit(ctx);
int index = ctx->add_name(b);
ctx->emit(OP_DELETE_ATTR, index, line);
return true;
}
bool emit_store(CodeEmitContext* ctx) override {
a->emit(ctx);
int index = ctx->add_name(b);
ctx->emit(OP_STORE_ATTR, index, line);
return true;
} }
}; };
// PASS
struct CallExpr: Expr{ struct CallExpr: Expr{
Expr_ callable; Expr_ callable;
std::vector<Expr_> args; std::vector<Expr_> args;
std::vector<std::pair<Str, Expr_>> kwargs; std::vector<std::pair<Str, Expr_>> kwargs;
Str str() const override { return "()"; } Str str() const override { return "call(...)"; }
std::vector<const Expr*> children() const override {
std::vector<const Expr*> ret;
for(auto& item: args) ret.push_back(item.get());
// ...ignore kwargs for simplicity
return ret;
}
bool need_unpack() const {
for(auto& item: args) if(item->is_starred()) return true;
return false;
}
void emit(CodeEmitContext* ctx) override {
callable->emit(ctx);
int KWARGC = (int)kwargs.size();
int ARGC = (int)args.size();
if(KWARGC > 0){
ctx->emit(need_unpack() ? OP_CALL_KWARGS_UNPACK : OP_CALL_KWARGS, (KWARGC<<16)|ARGC, line);
}else{
ctx->emit(need_unpack() ? OP_CALL_UNPACK : OP_CALL, ARGC, line);
}
}
}; };
struct BinaryExpr: Expr{ struct BinaryExpr: Expr{
@ -426,6 +531,10 @@ struct BinaryExpr: Expr{
Expr_ rhs; Expr_ rhs;
Str str() const override { return TK_STR(op); } Str str() const override { return TK_STR(op); }
std::vector<const Expr*> children() const override {
return {lhs.get(), rhs.get()};
}
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {
lhs->emit(ctx); lhs->emit(ctx);
rhs->emit(ctx); rhs->emit(ctx);
@ -459,13 +568,18 @@ struct BinaryExpr: Expr{
} }
}; };
// PASS
struct TernaryExpr: Expr{ struct TernaryExpr: Expr{
Expr_ cond; Expr_ cond;
Expr_ true_expr; Expr_ true_expr;
Expr_ false_expr; Expr_ false_expr;
Str str() const override { Str str() const override {
return "cond ? true_expr : false_expr"; return "cond ? t : f";
}
std::vector<const Expr*> children() const override {
return {cond.get(), true_expr.get(), false_expr.get()};
} }
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {

View File

@ -53,34 +53,20 @@ struct Frame {
// return ss.str(); // return ss.str();
// } // }
PyObject* pop(){ void pop(){
#if DEBUG_EXTRA_CHECK
if(_data.empty()) throw std::runtime_error("_data.empty() is true");
#endif
PyObject* v = _data.back();
_data.pop_back();
return v;
}
void _pop(){
#if DEBUG_EXTRA_CHECK #if DEBUG_EXTRA_CHECK
if(_data.empty()) throw std::runtime_error("_data.empty() is true"); if(_data.empty()) throw std::runtime_error("_data.empty() is true");
#endif #endif
_data.pop_back(); _data.pop_back();
} }
void try_deref(VM*, PyObject*&); PyObject* popx(){
#if DEBUG_EXTRA_CHECK
PyObject* pop_value(VM* vm){ if(_data.empty()) throw std::runtime_error("_data.empty() is true");
PyObject* value = pop(); #endif
try_deref(vm, value); PyObject* ret = _data.back();
return value; _data.pop_back();
} return ret;
PyObject* top_value(VM* vm){
PyObject* value = top();
try_deref(vm, value);
return value;
} }
PyObject*& top(){ PyObject*& top(){
@ -141,18 +127,9 @@ struct Frame {
} }
} }
Args pop_n_values_reversed(VM* vm, int n){
Args v(n);
for(int i=n-1; i>=0; i--){
v[i] = pop();
try_deref(vm, v[i]);
}
return v;
}
Args pop_n_reversed(int n){ Args pop_n_reversed(int n){
Args v(n); Args v(n);
for(int i=n-1; i>=0; i--) v[i] = pop(); for(int i=n-1; i>=0; i--) v[i] = popx();
return v; return v;
} }

View File

@ -71,7 +71,6 @@ OPCODE(BUILD_ATTR_REF)
OPCODE(STORE_NAME) OPCODE(STORE_NAME)
OPCODE(STORE_FUNCTION) OPCODE(STORE_FUNCTION)
OPCODE(STORE_REF) OPCODE(STORE_REF)
OPCODE(DELETE_REF)
OPCODE(TRY_BLOCK_ENTER) OPCODE(TRY_BLOCK_ENTER)
OPCODE(TRY_BLOCK_EXIT) OPCODE(TRY_BLOCK_EXIT)
@ -89,4 +88,20 @@ OPCODE(BEGIN_CLASS)
OPCODE(END_CLASS) OPCODE(END_CLASS)
OPCODE(STORE_CLASS_ATTR) OPCODE(STORE_CLASS_ATTR)
/**************************/
OPCODE(LOAD_NAME)
OPCODE(LOAD_ATTR)
OPCODE(LOAD_SUBSCR)
OPCODE(STORE_LOCAL)
OPCODE(STORE_GLOBAL)
OPCODE(STORE_ATTR)
OPCODE(STORE_SUBSCR)
OPCODE(DELETE_LOCAL)
OPCODE(DELETE_GLOBAL)
OPCODE(DELETE_ATTR)
OPCODE(DELETE_SUBSCR)
/**************************/
#endif #endif

View File

@ -83,11 +83,6 @@ struct AttrRef : BaseRef {
vm->setattr(obj, attr.name(), std::move(val)); vm->setattr(obj, attr.name(), std::move(val));
} }
void del(VM* vm, Frame* frame) const{
if(!obj->is_attr_valid()) vm->TypeError("cannot delete attribute");
if(!obj->attr().contains(attr.name())) vm->AttributeError(obj, attr.name());
obj->attr().erase(attr.name());
}
}; };
struct IndexRef : BaseRef { struct IndexRef : BaseRef {