mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-23 13:00:17 +00:00
up
This commit is contained in:
parent
ebe3193327
commit
718ba988d5
@ -448,8 +448,9 @@ class Compiler {
|
|||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
name = prev().str();
|
name = prev().str();
|
||||||
}
|
}
|
||||||
int index = ctx()->add_name(name, name_scope());
|
int index = ctx()->add_name(name);
|
||||||
ctx()->emit(OP_STORE_NAME, index, prev().line);
|
auto op = name_scope()==NAME_LOCAL ? OP_STORE_LOCAL : OP_STORE_GLOBAL;
|
||||||
|
ctx()->emit(op, index, prev().line);
|
||||||
} while (match(TK(",")));
|
} while (match(TK(",")));
|
||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
}
|
}
|
||||||
@ -459,8 +460,8 @@ class Compiler {
|
|||||||
_compile_import();
|
_compile_import();
|
||||||
consume(TK("import"));
|
consume(TK("import"));
|
||||||
if (match(TK("*"))) {
|
if (match(TK("*"))) {
|
||||||
if(name_scope() != NAME_GLOBAL) SyntaxError("import * can only be used in global scope");
|
if(name_scope() != NAME_GLOBAL) SyntaxError("import * should be used in global scope");
|
||||||
ctx()->emit(OP_STORE_ALL_NAMES, BC_NOARG, prev().line);
|
ctx()->emit(OP_IMPORT_STAR, BC_NOARG, prev().line);
|
||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -475,7 +476,8 @@ class Compiler {
|
|||||||
name = prev().str();
|
name = prev().str();
|
||||||
}
|
}
|
||||||
index = ctx()->add_name(name);
|
index = ctx()->add_name(name);
|
||||||
ctx()->emit(OP_STORE_GLOBAL, index, prev().line);
|
auto op = name_scope()==NAME_LOCAL ? OP_STORE_LOCAL : OP_STORE_GLOBAL;
|
||||||
|
ctx()->emit(op, index, prev().line);
|
||||||
} while (match(TK(",")));
|
} while (match(TK(",")));
|
||||||
ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
@ -527,6 +529,7 @@ class Compiler {
|
|||||||
ctx()->exit_block();
|
ctx()->exit_block();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PASS
|
||||||
void compile_for_loop() {
|
void compile_for_loop() {
|
||||||
EXPR_TUPLE();
|
EXPR_TUPLE();
|
||||||
Expr_ vars = ctx()->s_expr.popx();
|
Expr_ vars = ctx()->s_expr.popx();
|
||||||
@ -535,42 +538,39 @@ class Compiler {
|
|||||||
ctx()->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
|
||||||
ctx()->enter_block(FOR_LOOP);
|
ctx()->enter_block(FOR_LOOP);
|
||||||
ctx()->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
|
||||||
// set variables and handle implicit unpack
|
|
||||||
bool ok = vars->emit_store(ctx());
|
bool ok = vars->emit_store(ctx());
|
||||||
// this error occurs in `vars` instead of this line
|
if(!ok) SyntaxError(); // this error occurs in `vars` instead of this line, but...nevermind
|
||||||
// but...nevermind
|
|
||||||
if(!ok) SyntaxError();
|
|
||||||
compile_block_body();
|
compile_block_body();
|
||||||
ctx()->emit(OP_LOOP_CONTINUE, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit(OP_LOOP_CONTINUE, BC_NOARG, BC_KEEPLINE);
|
||||||
ctx()->exit_block();
|
ctx()->exit_block();
|
||||||
}
|
}
|
||||||
|
|
||||||
void compile_try_except() {
|
void compile_try_except() {
|
||||||
ctx()->enter_block(TRY_EXCEPT);
|
// ctx()->enter_block(TRY_EXCEPT);
|
||||||
ctx()->emit(OP_TRY_BLOCK_ENTER, BC_NOARG, prev().line);
|
// ctx()->emit(OP_TRY_BLOCK_ENTER, BC_NOARG, prev().line);
|
||||||
compile_block_body();
|
// compile_block_body();
|
||||||
ctx()->emit(OP_TRY_BLOCK_EXIT, BC_NOARG, BC_KEEPLINE);
|
// ctx()->emit(OP_TRY_BLOCK_EXIT, BC_NOARG, BC_KEEPLINE);
|
||||||
std::vector<int> patches = {
|
// std::vector<int> patches = {
|
||||||
ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE)
|
// ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE)
|
||||||
};
|
// };
|
||||||
ctx()->exit_block();
|
// ctx()->exit_block();
|
||||||
|
|
||||||
do {
|
// do {
|
||||||
consume(TK("except"));
|
// consume(TK("except"));
|
||||||
if(match(TK("@id"))){
|
// if(match(TK("@id"))){
|
||||||
int name_idx = ctx()->add_name(prev().str(), NAME_SPECIAL);
|
// int name_idx = ctx()->add_name(prev().str(), NAME_SPECIAL);
|
||||||
emit(OP_EXCEPTION_MATCH, name_idx);
|
// emit(OP_EXCEPTION_MATCH, name_idx);
|
||||||
}else{
|
// }else{
|
||||||
emit(OP_LOAD_TRUE);
|
// emit(OP_LOAD_TRUE);
|
||||||
}
|
// }
|
||||||
int patch = emit(OP_POP_JUMP_IF_FALSE);
|
// int patch = emit(OP_POP_JUMP_IF_FALSE);
|
||||||
emit(OP_POP_TOP); // pop the exception on match
|
// emit(OP_POP_TOP); // pop the exception on match
|
||||||
compile_block_body();
|
// compile_block_body();
|
||||||
patches.push_back(emit(OP_JUMP_ABSOLUTE));
|
// patches.push_back(emit(OP_JUMP_ABSOLUTE));
|
||||||
patch_jump(patch);
|
// patch_jump(patch);
|
||||||
}while(curr().type == TK("except"));
|
// }while(curr().type == TK("except"));
|
||||||
emit(OP_RE_RAISE); // no match, re-raise
|
// emit(OP_RE_RAISE); // no match, re-raise
|
||||||
for (int patch : patches) patch_jump(patch);
|
// for (int patch : patches) patch_jump(patch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void compile_decorated(){
|
void compile_decorated(){
|
||||||
@ -650,13 +650,13 @@ class Compiler {
|
|||||||
case TK("global"):
|
case TK("global"):
|
||||||
do {
|
do {
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
co()->global_names.insert(prev().str());
|
ctx()->co->global_names.insert(prev().str());
|
||||||
} while (match(TK(",")));
|
} while (match(TK(",")));
|
||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
break;
|
break;
|
||||||
case TK("raise"): {
|
case TK("raise"): {
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
int dummy_t = ctx()->add_name(prev().str(), NAME_SPECIAL);
|
int dummy_t = ctx()->add_name(prev().str());
|
||||||
if(match(TK("(")) && !match(TK(")"))){
|
if(match(TK("(")) && !match(TK(")"))){
|
||||||
EXPR(false); consume(TK(")"));
|
EXPR(false); consume(TK(")"));
|
||||||
}else{
|
}else{
|
||||||
@ -688,17 +688,17 @@ class Compiler {
|
|||||||
} break;
|
} break;
|
||||||
/*************************************************/
|
/*************************************************/
|
||||||
// TODO: refactor goto/label use special $ syntax
|
// TODO: refactor goto/label use special $ syntax
|
||||||
case TK("label"):
|
case TK("label"): {
|
||||||
if(mode()!=EXEC_MODE) SyntaxError("'label' is only available in EXEC_MODE");
|
if(mode()!=EXEC_MODE) SyntaxError("'label' is only available in EXEC_MODE");
|
||||||
consume(TK(".")); consume(TK("@id"));
|
consume(TK(".")); consume(TK("@id"));
|
||||||
bool ok = ctx()->add_label(prev().str());
|
bool ok = ctx()->add_label(prev().str());
|
||||||
if(!ok) SyntaxError("label " + prev().str().escape(true) + " already exists");
|
if(!ok) SyntaxError("label " + prev().str().escape(true) + " already exists");
|
||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
break;
|
} break;
|
||||||
case TK("goto"):
|
case TK("goto"):
|
||||||
if(mode()!=EXEC_MODE) SyntaxError("'goto' is only available in EXEC_MODE");
|
if(mode()!=EXEC_MODE) SyntaxError("'goto' is only available in EXEC_MODE");
|
||||||
consume(TK(".")); consume(TK("@id"));
|
consume(TK(".")); consume(TK("@id"));
|
||||||
emit(OP_GOTO, co()->add_name(prev().str(), NAME_SPECIAL));
|
ctx()->emit(OP_GOTO, ctx()->add_name(prev().str()), prev().line);
|
||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
break;
|
break;
|
||||||
/*************************************************/
|
/*************************************************/
|
||||||
@ -707,9 +707,9 @@ class Compiler {
|
|||||||
EXPR_TUPLE(true);
|
EXPR_TUPLE(true);
|
||||||
if(!try_compile_assignment()){
|
if(!try_compile_assignment()){
|
||||||
if(mode()==REPL_MODE && name_scope()==NAME_GLOBAL){
|
if(mode()==REPL_MODE && name_scope()==NAME_GLOBAL){
|
||||||
emit(OP_PRINT_EXPR, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit(OP_PRINT_EXPR, BC_NOARG, BC_KEEPLINE);
|
||||||
}else{
|
}else{
|
||||||
emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
@ -717,21 +717,22 @@ class Compiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PASS
|
||||||
void compile_class(){
|
void compile_class(){
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
int cls_name_idx = co()->add_name(prev().str(), NAME_GLOBAL);
|
int namei = ctx()->add_name(prev().str());
|
||||||
int super_cls_name_idx = -1;
|
int super_namei = -1;
|
||||||
if(match(TK("(")) && match(TK("@id"))){
|
if(match(TK("(")) && match(TK("@id"))){
|
||||||
super_cls_name_idx = co()->add_name(prev().str(), NAME_GLOBAL);
|
super_namei = ctx()->add_name(prev().str());
|
||||||
consume(TK(")"));
|
consume(TK(")"));
|
||||||
}
|
}
|
||||||
if(super_cls_name_idx == -1) emit(OP_LOAD_NONE);
|
if(super_namei == -1) ctx()->emit(OP_LOAD_NONE, BC_NOARG, prev().line);
|
||||||
else emit(OP_LOAD_NAME, super_cls_name_idx);
|
else ctx()->emit(OP_LOAD_NAME, super_namei, prev().line);
|
||||||
emit(OP_BEGIN_CLASS, cls_name_idx);
|
ctx()->emit(OP_BEGIN_CLASS, namei, BC_KEEPLINE);
|
||||||
ctx()->is_compiling_class = true;
|
ctx()->is_compiling_class = true;
|
||||||
compile_block_body();
|
compile_block_body();
|
||||||
ctx()->is_compiling_class = false;
|
ctx()->is_compiling_class = false;
|
||||||
emit(OP_END_CLASS);
|
ctx()->emit(OP_END_CLASS, BC_NOARG, BC_KEEPLINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _compile_f_args(Function& func, bool enable_type_hints){
|
void _compile_f_args(Function& func, bool enable_type_hints){
|
||||||
|
38
src/expr.h
38
src/expr.h
@ -23,7 +23,7 @@ struct Expr{
|
|||||||
virtual bool emit_del(CodeEmitContext* ctx) { return false; }
|
virtual bool emit_del(CodeEmitContext* ctx) { return false; }
|
||||||
|
|
||||||
// for OP_STORE_XXX
|
// for OP_STORE_XXX
|
||||||
virtual bool emit_store(CodeEmitContext* ctx) { return false; }
|
[[nodiscard]] virtual bool emit_store(CodeEmitContext* ctx) { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CodeEmitContext{
|
struct CodeEmitContext{
|
||||||
@ -153,15 +153,12 @@ struct StarredExpr: Expr{
|
|||||||
|
|
||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
child->emit(ctx);
|
child->emit(ctx);
|
||||||
// as a rvalue, we should do unpack here
|
ctx->emit(OP_UNARY_STAR, BC_NOARG, line);
|
||||||
//ctx->emit(OP_UNARY_STAR, (int)false, line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool emit_store(CodeEmitContext* ctx) override {
|
bool emit_store(CodeEmitContext* ctx) override {
|
||||||
child->emit(ctx);
|
// simply proxy to child
|
||||||
// as a lvalue, we should do pack here
|
return child->emit_store(ctx);
|
||||||
//ctx->emit(OP_UNARY_STAR, (int)true, line);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -368,10 +365,29 @@ struct TupleExpr: SequenceExpr{
|
|||||||
Opcode opcode() const override { return OP_BUILD_TUPLE; }
|
Opcode opcode() const override { return OP_BUILD_TUPLE; }
|
||||||
|
|
||||||
bool emit_store(CodeEmitContext* ctx) override {
|
bool emit_store(CodeEmitContext* ctx) override {
|
||||||
// assume TOS is an iterable
|
// TOS is an iterable
|
||||||
// unpack it and emit several OP_STORE
|
// items may contain StarredExpr, we should check it
|
||||||
// https://docs.python.org/3/library/dis.html#opcode-UNPACK_SEQUENCE
|
int starred_i = -1;
|
||||||
// https://docs.python.org/3/library/dis.html#opcode-UNPACK_EX
|
for(int i=0; i<items.size(); i++){
|
||||||
|
if(!items[i]->is_starred()) continue;
|
||||||
|
if(starred_i == -1) starred_i = i;
|
||||||
|
else return false; // multiple StarredExpr not allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
if(starred_i == -1){
|
||||||
|
// Unpacks TOS into count individual values, which are put onto the stack right-to-left.
|
||||||
|
ctx->emit(OP_UNPACK_SEQUENCE, items.size(), line);
|
||||||
|
}else{
|
||||||
|
// starred assignment target must be in a tuple
|
||||||
|
if(items.size() == 1) return false;
|
||||||
|
// starred assignment target must be the last one (differ from CPython)
|
||||||
|
if(starred_i != items.size()-1) return false;
|
||||||
|
ctx->emit(OP_UNPACK_EX, items.size()-1, line);
|
||||||
|
}
|
||||||
|
for(auto& e: items){
|
||||||
|
bool ok = e->emit_store(ctx);
|
||||||
|
if(!ok) return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,5 +94,7 @@ OPCODE(FOR_ITER)
|
|||||||
OPCODE(IMPORT_NAME)
|
OPCODE(IMPORT_NAME)
|
||||||
OPCODE(IMPORT_STAR)
|
OPCODE(IMPORT_STAR)
|
||||||
/**************************/
|
/**************************/
|
||||||
|
OPCODE(UNPACK_SEQUENCE)
|
||||||
|
OPCODE(UNPACK_EX)
|
||||||
/**************************/
|
/**************************/
|
||||||
#endif
|
#endif
|
Loading…
x
Reference in New Issue
Block a user