mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
rename emit
into emit_
to make QT happy
This commit is contained in:
parent
f3acafe44c
commit
901f702f00
@ -15,7 +15,7 @@ typedef std::unique_ptr<Expr> Expr_;
|
||||
struct Expr{
|
||||
int line = 0;
|
||||
virtual ~Expr() = default;
|
||||
virtual void emit(CodeEmitContext* ctx) = 0;
|
||||
virtual void emit_(CodeEmitContext* ctx) = 0;
|
||||
virtual bool is_literal() const { return false; }
|
||||
virtual bool is_json_object() const { return false; }
|
||||
virtual bool is_attrib() const { return false; }
|
||||
@ -60,7 +60,7 @@ struct CodeEmitContext{
|
||||
void exit_block();
|
||||
void emit_expr(); // clear the expression stack and generate bytecode
|
||||
std::string _log_s_expr();
|
||||
int emit(Opcode opcode, uint16_t arg, int line);
|
||||
int emit_(Opcode opcode, uint16_t arg, int line);
|
||||
void patch_jump(int index);
|
||||
bool add_label(StrName name);
|
||||
int add_varname(StrName name);
|
||||
@ -73,7 +73,7 @@ struct NameExpr: Expr{
|
||||
StrName name;
|
||||
NameScope scope;
|
||||
NameExpr(StrName name, NameScope scope): name(name), scope(scope) {}
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
bool emit_del(CodeEmitContext* ctx) override;
|
||||
bool emit_store(CodeEmitContext* ctx) override;
|
||||
bool is_name() const override { return true; }
|
||||
@ -82,7 +82,7 @@ struct NameExpr: Expr{
|
||||
struct InvertExpr: Expr{
|
||||
Expr_ child;
|
||||
InvertExpr(Expr_&& child): child(std::move(child)) {}
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
struct StarredExpr: Expr{
|
||||
@ -90,26 +90,26 @@ struct StarredExpr: Expr{
|
||||
Expr_ child;
|
||||
StarredExpr(int level, Expr_&& child): level(level), child(std::move(child)) {}
|
||||
int star_level() const override { return level; }
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
bool emit_store(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
struct NotExpr: Expr{
|
||||
Expr_ child;
|
||||
NotExpr(Expr_&& child): child(std::move(child)) {}
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
struct AndExpr: Expr{
|
||||
Expr_ lhs;
|
||||
Expr_ rhs;
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
struct OrExpr: Expr{
|
||||
Expr_ lhs;
|
||||
Expr_ rhs;
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
// [None, True, False, ...]
|
||||
@ -118,26 +118,26 @@ struct Literal0Expr: Expr{
|
||||
Literal0Expr(TokenIndex token): token(token) {}
|
||||
bool is_json_object() const override { return true; }
|
||||
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
struct LongExpr: Expr{
|
||||
Str s;
|
||||
LongExpr(const Str& s): s(s) {}
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
struct BytesExpr: Expr{
|
||||
Str s;
|
||||
BytesExpr(const Str& s): s(s) {}
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
// @num, @str which needs to invoke OP_LOAD_CONST
|
||||
struct LiteralExpr: Expr{
|
||||
TokenValue value;
|
||||
LiteralExpr(TokenValue value): value(value) {}
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
bool is_literal() const override { return true; }
|
||||
bool is_json_object() const override { return true; }
|
||||
};
|
||||
@ -145,7 +145,7 @@ struct LiteralExpr: Expr{
|
||||
struct NegatedExpr: Expr{
|
||||
Expr_ child;
|
||||
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(); }
|
||||
};
|
||||
|
||||
@ -153,14 +153,14 @@ struct SliceExpr: Expr{
|
||||
Expr_ start;
|
||||
Expr_ stop;
|
||||
Expr_ step;
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
struct DictItemExpr: Expr{
|
||||
Expr_ key; // maybe nullptr if it is **kwargs
|
||||
Expr_ value;
|
||||
int star_level() const override { return value->star_level(); }
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
struct SequenceExpr: Expr{
|
||||
@ -168,9 +168,9 @@ struct SequenceExpr: Expr{
|
||||
SequenceExpr(std::vector<Expr_>&& items): items(std::move(items)) {}
|
||||
virtual Opcode opcode() const = 0;
|
||||
|
||||
void emit(CodeEmitContext* ctx) override {
|
||||
for(auto& item: items) item->emit(ctx);
|
||||
ctx->emit(opcode(), items.size(), line);
|
||||
void emit_(CodeEmitContext* ctx) override {
|
||||
for(auto& item: items) item->emit_(ctx);
|
||||
ctx->emit_(opcode(), items.size(), line);
|
||||
}
|
||||
};
|
||||
|
||||
@ -223,7 +223,7 @@ struct CompExpr: Expr{
|
||||
virtual Opcode op0() = 0;
|
||||
virtual Opcode op1() = 0;
|
||||
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
struct ListCompExpr: CompExpr{
|
||||
@ -246,9 +246,9 @@ struct LambdaExpr: Expr{
|
||||
|
||||
LambdaExpr(FuncDecl_ decl): decl(decl) {}
|
||||
|
||||
void emit(CodeEmitContext* ctx) override {
|
||||
void emit_(CodeEmitContext* ctx) override {
|
||||
int index = ctx->add_func_decl(decl);
|
||||
ctx->emit(OP_LOAD_FUNCTION, index, line);
|
||||
ctx->emit_(OP_LOAD_FUNCTION, index, line);
|
||||
}
|
||||
};
|
||||
|
||||
@ -256,13 +256,13 @@ struct FStringExpr: Expr{
|
||||
Str src;
|
||||
FStringExpr(const Str& src): src(src) {}
|
||||
void _load_simple_expr(CodeEmitContext* ctx, Str expr);
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
struct SubscrExpr: Expr{
|
||||
Expr_ a;
|
||||
Expr_ b;
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
bool emit_del(CodeEmitContext* ctx) override;
|
||||
bool emit_store(CodeEmitContext* ctx) override;
|
||||
};
|
||||
@ -273,7 +273,7 @@ struct AttribExpr: Expr{
|
||||
AttribExpr(Expr_ a, const Str& b): a(std::move(a)), b(b) {}
|
||||
AttribExpr(Expr_ a, Str&& b): a(std::move(a)), b(std::move(b)) {}
|
||||
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
bool emit_del(CodeEmitContext* ctx) override;
|
||||
bool emit_store(CodeEmitContext* ctx) override;
|
||||
void emit_method(CodeEmitContext* ctx);
|
||||
@ -285,15 +285,15 @@ struct CallExpr: Expr{
|
||||
std::vector<Expr_> args;
|
||||
// **a will be interpreted as a special keyword argument: {"**": a}
|
||||
std::vector<std::pair<Str, Expr_>> kwargs;
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
struct GroupedExpr: Expr{
|
||||
Expr_ a;
|
||||
GroupedExpr(Expr_&& a): a(std::move(a)) {}
|
||||
|
||||
void emit(CodeEmitContext* ctx) override{
|
||||
a->emit(ctx);
|
||||
void emit_(CodeEmitContext* ctx) override{
|
||||
a->emit_(ctx);
|
||||
}
|
||||
|
||||
bool emit_del(CodeEmitContext* ctx) override {
|
||||
@ -311,7 +311,7 @@ struct BinaryExpr: Expr{
|
||||
Expr_ rhs;
|
||||
bool is_compare() const override;
|
||||
void _emit_compare(CodeEmitContext* ctx, std::vector<int>& jmps);
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
|
||||
@ -319,7 +319,7 @@ struct TernaryExpr: Expr{
|
||||
Expr_ cond;
|
||||
Expr_ true_expr;
|
||||
Expr_ false_expr;
|
||||
void emit(CodeEmitContext* ctx) override;
|
||||
void emit_(CodeEmitContext* ctx) override;
|
||||
};
|
||||
|
||||
|
||||
|
130
src/compiler.cpp
130
src/compiler.cpp
@ -30,8 +30,8 @@ namespace pkpy{
|
||||
// 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
|
||||
ctx()->emit(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||
// some check here
|
||||
std::vector<Bytecode>& codes = ctx()->co->codes;
|
||||
if(ctx()->co->varnames.size() > PK_MAX_CO_VARNAMES){
|
||||
@ -215,7 +215,7 @@ namespace pkpy{
|
||||
}
|
||||
// https://github.com/blueloveTH/pocketpy/issues/37
|
||||
parse_expression(PREC_LAMBDA + 1, false);
|
||||
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||
pop_context();
|
||||
ctx()->s_expr.push(std::move(e));
|
||||
}
|
||||
@ -518,7 +518,7 @@ __SUBSCR_END:
|
||||
do {
|
||||
consume(TK("@id"));
|
||||
Str name = prev().str();
|
||||
ctx()->emit(OP_IMPORT_PATH, ctx()->add_const(VAR(name)), prev().line);
|
||||
ctx()->emit_(OP_IMPORT_PATH, ctx()->add_const(VAR(name)), prev().line);
|
||||
if (match(TK("as"))) {
|
||||
consume(TK("@id"));
|
||||
name = prev().str();
|
||||
@ -570,29 +570,29 @@ __EAT_DOTS_END:
|
||||
}
|
||||
}
|
||||
|
||||
ctx()->emit(OP_IMPORT_PATH, ctx()->add_const(VAR(ss.str())), prev().line);
|
||||
ctx()->emit_(OP_IMPORT_PATH, ctx()->add_const(VAR(ss.str())), prev().line);
|
||||
consume(TK("import"));
|
||||
|
||||
if (match(TK("*"))) {
|
||||
if(name_scope() != NAME_GLOBAL) SyntaxError("from <module> import * can only be used in global scope");
|
||||
// pop the module and import __all__
|
||||
ctx()->emit(OP_POP_IMPORT_STAR, BC_NOARG, prev().line);
|
||||
ctx()->emit_(OP_POP_IMPORT_STAR, BC_NOARG, prev().line);
|
||||
consume_end_stmt();
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
ctx()->emit(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||
consume(TK("@id"));
|
||||
Str name = prev().str();
|
||||
ctx()->emit(OP_LOAD_ATTR, StrName(name).index, prev().line);
|
||||
ctx()->emit_(OP_LOAD_ATTR, StrName(name).index, prev().line);
|
||||
if (match(TK("as"))) {
|
||||
consume(TK("@id"));
|
||||
name = prev().str();
|
||||
}
|
||||
ctx()->emit_store_name(name_scope(), StrName(name), prev().line);
|
||||
} while (match(TK(",")));
|
||||
ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||
consume_end_stmt();
|
||||
}
|
||||
|
||||
@ -618,15 +618,15 @@ __EAT_DOTS_END:
|
||||
|
||||
void Compiler::compile_if_stmt() {
|
||||
EXPR(false); // condition
|
||||
int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line);
|
||||
int patch = ctx()->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line);
|
||||
compile_block_body();
|
||||
if (match(TK("elif"))) {
|
||||
int exit_patch = ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, prev().line);
|
||||
int exit_patch = ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, prev().line);
|
||||
ctx()->patch_jump(patch);
|
||||
compile_if_stmt();
|
||||
ctx()->patch_jump(exit_patch);
|
||||
} else if (match(TK("else"))) {
|
||||
int exit_patch = ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, prev().line);
|
||||
int exit_patch = ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, prev().line);
|
||||
ctx()->patch_jump(patch);
|
||||
compile_block_body();
|
||||
ctx()->patch_jump(exit_patch);
|
||||
@ -638,9 +638,9 @@ __EAT_DOTS_END:
|
||||
void Compiler::compile_while_loop() {
|
||||
CodeBlock* block = ctx()->enter_block(WHILE_LOOP);
|
||||
EXPR(false); // condition
|
||||
int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line);
|
||||
int patch = ctx()->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line);
|
||||
compile_block_body();
|
||||
ctx()->emit(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
|
||||
ctx()->emit_(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
|
||||
ctx()->patch_jump(patch);
|
||||
ctx()->exit_block();
|
||||
// optional else clause
|
||||
@ -654,13 +654,13 @@ __EAT_DOTS_END:
|
||||
Expr_ vars = EXPR_VARS();
|
||||
consume(TK("in"));
|
||||
EXPR_TUPLE(false);
|
||||
ctx()->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
|
||||
CodeBlock* block = ctx()->enter_block(FOR_LOOP);
|
||||
ctx()->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
|
||||
bool ok = vars->emit_store(ctx());
|
||||
if(!ok) SyntaxError(); // this error occurs in `vars` instead of this line, but...nevermind
|
||||
compile_block_body();
|
||||
ctx()->emit(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
|
||||
ctx()->emit_(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
|
||||
ctx()->exit_block();
|
||||
// optional else clause
|
||||
if (match(TK("else"))) {
|
||||
@ -673,25 +673,25 @@ __EAT_DOTS_END:
|
||||
ctx()->enter_block(TRY_EXCEPT);
|
||||
compile_block_body();
|
||||
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();
|
||||
do {
|
||||
consume(TK("except"));
|
||||
if(match(TK("@id"))){
|
||||
ctx()->emit(OP_EXCEPTION_MATCH, StrName(prev().sv()).index, prev().line);
|
||||
ctx()->emit_(OP_EXCEPTION_MATCH, StrName(prev().sv()).index, prev().line);
|
||||
}else{
|
||||
ctx()->emit(OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE);
|
||||
}
|
||||
int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
|
||||
int patch = ctx()->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
|
||||
// pop the exception on match
|
||||
ctx()->emit(OP_POP_EXCEPTION, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_POP_EXCEPTION, BC_NOARG, BC_KEEPLINE);
|
||||
compile_block_body();
|
||||
patches.push_back(ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE));
|
||||
patches.push_back(ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE));
|
||||
ctx()->patch_jump(patch);
|
||||
}while(curr().type == TK("except"));
|
||||
// no match, re-raise
|
||||
ctx()->emit(OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
|
||||
for (int patch : patches) ctx()->patch_jump(patch);
|
||||
}
|
||||
|
||||
@ -720,7 +720,7 @@ __EAT_DOTS_END:
|
||||
EXPR_TUPLE();
|
||||
e->rhs = ctx()->s_expr.popx();
|
||||
if(e->is_starred()) SyntaxError();
|
||||
e->emit(ctx());
|
||||
e->emit_(ctx());
|
||||
bool ok = lhs_p->emit_store(ctx());
|
||||
if(!ok) SyntaxError();
|
||||
} return true;
|
||||
@ -739,8 +739,8 @@ __EAT_DOTS_END:
|
||||
}
|
||||
// stack size is n+1
|
||||
Expr_ val = ctx()->s_expr.popx();
|
||||
val->emit(ctx());
|
||||
for(int j=1; j<n; j++) ctx()->emit(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||
val->emit_(ctx());
|
||||
for(int j=1; j<n; j++) ctx()->emit_(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||
for(int j=0; j<n; j++){
|
||||
auto e = ctx()->s_expr.popx();
|
||||
if(e->is_starred()) SyntaxError();
|
||||
@ -759,12 +759,12 @@ __EAT_DOTS_END:
|
||||
switch(prev().type){
|
||||
case TK("break"):
|
||||
if (curr_loop_block < 0) SyntaxError("'break' outside loop");
|
||||
ctx()->emit(OP_LOOP_BREAK, curr_loop_block, kw_line);
|
||||
ctx()->emit_(OP_LOOP_BREAK, curr_loop_block, kw_line);
|
||||
consume_end_stmt();
|
||||
break;
|
||||
case TK("continue"):
|
||||
if (curr_loop_block < 0) SyntaxError("'continue' not properly in loop");
|
||||
ctx()->emit(OP_LOOP_CONTINUE, curr_loop_block, kw_line);
|
||||
ctx()->emit_(OP_LOOP_CONTINUE, curr_loop_block, kw_line);
|
||||
consume_end_stmt();
|
||||
break;
|
||||
case TK("yield"):
|
||||
@ -772,7 +772,7 @@ __EAT_DOTS_END:
|
||||
EXPR_TUPLE(false);
|
||||
// if yield present, mark the function as generator
|
||||
ctx()->co->is_generator = true;
|
||||
ctx()->emit(OP_YIELD_VALUE, BC_NOARG, kw_line);
|
||||
ctx()->emit_(OP_YIELD_VALUE, BC_NOARG, kw_line);
|
||||
consume_end_stmt();
|
||||
break;
|
||||
case TK("yield from"):
|
||||
@ -780,23 +780,23 @@ __EAT_DOTS_END:
|
||||
EXPR_TUPLE(false);
|
||||
// if yield from present, mark the function as generator
|
||||
ctx()->co->is_generator = true;
|
||||
ctx()->emit(OP_GET_ITER, BC_NOARG, kw_line);
|
||||
ctx()->emit_(OP_GET_ITER, BC_NOARG, kw_line);
|
||||
ctx()->enter_block(FOR_LOOP);
|
||||
ctx()->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit(OP_YIELD_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
|
||||
ctx()->emit_(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_YIELD_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
|
||||
ctx()->exit_block();
|
||||
consume_end_stmt();
|
||||
break;
|
||||
case TK("return"):
|
||||
if (contexts.size() <= 1) SyntaxError("'return' outside function");
|
||||
if(match_end_stmt()){
|
||||
ctx()->emit(OP_LOAD_NONE, BC_NOARG, kw_line);
|
||||
ctx()->emit_(OP_LOAD_NONE, BC_NOARG, kw_line);
|
||||
}else{
|
||||
EXPR_TUPLE(false);
|
||||
consume_end_stmt();
|
||||
}
|
||||
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, kw_line);
|
||||
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, kw_line);
|
||||
break;
|
||||
/*************************************************/
|
||||
case TK("if"): compile_if_stmt(); break;
|
||||
@ -817,10 +817,10 @@ __EAT_DOTS_END:
|
||||
if(is_global) scope = NAME_GLOBAL;
|
||||
switch(scope){
|
||||
case NAME_LOCAL:
|
||||
ctx()->emit(OP_INC_FAST, ctx()->add_varname(name), prev().line);
|
||||
ctx()->emit_(OP_INC_FAST, ctx()->add_varname(name), prev().line);
|
||||
break;
|
||||
case NAME_GLOBAL:
|
||||
ctx()->emit(OP_INC_GLOBAL, name.index, prev().line);
|
||||
ctx()->emit_(OP_INC_GLOBAL, name.index, prev().line);
|
||||
break;
|
||||
default: SyntaxError(); break;
|
||||
}
|
||||
@ -832,10 +832,10 @@ __EAT_DOTS_END:
|
||||
StrName name(prev().sv());
|
||||
switch(name_scope()){
|
||||
case NAME_LOCAL:
|
||||
ctx()->emit(OP_DEC_FAST, ctx()->add_varname(name), prev().line);
|
||||
ctx()->emit_(OP_DEC_FAST, ctx()->add_varname(name), prev().line);
|
||||
break;
|
||||
case NAME_GLOBAL:
|
||||
ctx()->emit(OP_DEC_GLOBAL, name.index, prev().line);
|
||||
ctx()->emit_(OP_DEC_GLOBAL, name.index, prev().line);
|
||||
break;
|
||||
default: SyntaxError(); break;
|
||||
}
|
||||
@ -844,13 +844,13 @@ __EAT_DOTS_END:
|
||||
}
|
||||
case TK("assert"):{
|
||||
EXPR(false); // condition
|
||||
int index = ctx()->emit(OP_POP_JUMP_IF_TRUE, BC_NOARG, kw_line);
|
||||
int index = ctx()->emit_(OP_POP_JUMP_IF_TRUE, BC_NOARG, kw_line);
|
||||
int has_msg = 0;
|
||||
if(match(TK(","))){
|
||||
EXPR(false); // message
|
||||
has_msg = 1;
|
||||
}
|
||||
ctx()->emit(OP_RAISE_ASSERT, has_msg, kw_line);
|
||||
ctx()->emit_(OP_RAISE_ASSERT, has_msg, kw_line);
|
||||
ctx()->patch_jump(index);
|
||||
consume_end_stmt();
|
||||
break;
|
||||
@ -868,9 +868,9 @@ __EAT_DOTS_END:
|
||||
if(match(TK("(")) && !match(TK(")"))){
|
||||
EXPR(false); consume(TK(")"));
|
||||
}else{
|
||||
ctx()->emit(OP_LOAD_NONE, BC_NOARG, kw_line);
|
||||
ctx()->emit_(OP_LOAD_NONE, BC_NOARG, kw_line);
|
||||
}
|
||||
ctx()->emit(OP_RAISE, dummy_t, kw_line);
|
||||
ctx()->emit_(OP_RAISE, dummy_t, kw_line);
|
||||
consume_end_stmt();
|
||||
} break;
|
||||
case TK("del"): {
|
||||
@ -887,11 +887,11 @@ __EAT_DOTS_END:
|
||||
Expr_ e = make_expr<NameExpr>(prev().str(), name_scope());
|
||||
bool ok = e->emit_store(ctx());
|
||||
if(!ok) SyntaxError();
|
||||
e->emit(ctx());
|
||||
ctx()->emit(OP_WITH_ENTER, BC_NOARG, prev().line);
|
||||
e->emit_(ctx());
|
||||
ctx()->emit_(OP_WITH_ENTER, BC_NOARG, prev().line);
|
||||
compile_block_body();
|
||||
e->emit(ctx());
|
||||
ctx()->emit(OP_WITH_EXIT, BC_NOARG, prev().line);
|
||||
e->emit_(ctx());
|
||||
ctx()->emit_(OP_WITH_EXIT, BC_NOARG, prev().line);
|
||||
} break;
|
||||
/*************************************************/
|
||||
case TK("=="): {
|
||||
@ -905,7 +905,7 @@ __EAT_DOTS_END:
|
||||
case TK("->"):
|
||||
consume(TK("@id"));
|
||||
if(mode()!=EXEC_MODE) SyntaxError("'goto' is only available in EXEC_MODE");
|
||||
ctx()->emit(OP_GOTO, StrName(prev().sv()).index, prev().line);
|
||||
ctx()->emit_(OP_GOTO, StrName(prev().sv()).index, prev().line);
|
||||
consume_end_stmt();
|
||||
break;
|
||||
/*************************************************/
|
||||
@ -929,9 +929,9 @@ __EAT_DOTS_END:
|
||||
if(!is_typed_name){
|
||||
ctx()->emit_expr();
|
||||
if((mode()==CELL_MODE || mode()==REPL_MODE) && name_scope()==NAME_GLOBAL){
|
||||
ctx()->emit(OP_PRINT_EXPR, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_PRINT_EXPR, BC_NOARG, BC_KEEPLINE);
|
||||
}else{
|
||||
ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||
}
|
||||
}else{
|
||||
PK_ASSERT(ctx()->s_expr.size() == 1)
|
||||
@ -960,15 +960,15 @@ __EAT_DOTS_END:
|
||||
consume(TK(")"));
|
||||
}
|
||||
if(base == nullptr){
|
||||
ctx()->emit(OP_LOAD_NONE, BC_NOARG, prev().line);
|
||||
ctx()->emit_(OP_LOAD_NONE, BC_NOARG, prev().line);
|
||||
}else {
|
||||
base->emit(ctx());
|
||||
base->emit_(ctx());
|
||||
}
|
||||
ctx()->emit(OP_BEGIN_CLASS, namei, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_BEGIN_CLASS, namei, BC_KEEPLINE);
|
||||
ctx()->is_compiling_class = true;
|
||||
compile_block_body();
|
||||
ctx()->is_compiling_class = false;
|
||||
ctx()->emit(OP_END_CLASS, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_END_CLASS, BC_NOARG, BC_KEEPLINE);
|
||||
}
|
||||
|
||||
void Compiler::_compile_f_args(FuncDecl_ decl, bool enable_type_hints){
|
||||
@ -1062,22 +1062,22 @@ __EAT_DOTS_END:
|
||||
if(docstring != nullptr){
|
||||
decl->docstring = PK_OBJ_GET(Str, docstring);
|
||||
}
|
||||
ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_func_decl(decl), prev().line);
|
||||
ctx()->emit_(OP_LOAD_FUNCTION, ctx()->add_func_decl(decl), prev().line);
|
||||
|
||||
// add decorators
|
||||
for(auto it=decorators.rbegin(); it!=decorators.rend(); ++it){
|
||||
(*it)->emit(ctx());
|
||||
ctx()->emit(OP_ROT_TWO, BC_NOARG, (*it)->line);
|
||||
ctx()->emit(OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit(OP_ROT_TWO, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit(OP_CALL, 1, (*it)->line);
|
||||
(*it)->emit_(ctx());
|
||||
ctx()->emit_(OP_ROT_TWO, BC_NOARG, (*it)->line);
|
||||
ctx()->emit_(OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_ROT_TWO, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_CALL, 1, (*it)->line);
|
||||
}
|
||||
if(!ctx()->is_compiling_class){
|
||||
auto e = make_expr<NameExpr>(decl_name, name_scope());
|
||||
e->emit_store(ctx());
|
||||
}else{
|
||||
int index = StrName(decl_name).index;
|
||||
ctx()->emit(OP_STORE_CLASS_ATTR, index, prev().line);
|
||||
ctx()->emit_(OP_STORE_CLASS_ATTR, index, prev().line);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1143,7 +1143,7 @@ __EAT_DOTS_END:
|
||||
if(mode()==EVAL_MODE) {
|
||||
EXPR_TUPLE(false);
|
||||
consume(TK("@eof"));
|
||||
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||
pop_context();
|
||||
return code;
|
||||
}else if(mode()==JSON_MODE){
|
||||
@ -1151,8 +1151,8 @@ __EAT_DOTS_END:
|
||||
Expr_ e = ctx()->s_expr.popx();
|
||||
if(!e->is_json_object()) SyntaxError("expect a JSON object, literal or array");
|
||||
consume(TK("@eof"));
|
||||
e->emit(ctx());
|
||||
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||
e->emit_(ctx());
|
||||
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||
pop_context();
|
||||
return code;
|
||||
}
|
||||
|
332
src/expr.cpp
332
src/expr.cpp
@ -30,7 +30,7 @@ namespace pkpy{
|
||||
|
||||
if(curr_type == FOR_LOOP){
|
||||
// add a no op here to make block check work
|
||||
emit(OP_NO_OP, BC_NOARG, BC_KEEPLINE);
|
||||
emit_(OP_NO_OP, BC_NOARG, BC_KEEPLINE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ namespace pkpy{
|
||||
throw std::runtime_error("s_expr.size() != 1\n" + _log_s_expr());
|
||||
}
|
||||
Expr_ expr = s_expr.popx();
|
||||
expr->emit(this);
|
||||
expr->emit_(this);
|
||||
}
|
||||
|
||||
std::string CodeEmitContext::_log_s_expr(){
|
||||
@ -49,7 +49,7 @@ namespace pkpy{
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
int CodeEmitContext::emit(Opcode opcode, uint16_t arg, int line) {
|
||||
int CodeEmitContext::emit_(Opcode opcode, uint16_t arg, int line) {
|
||||
co->codes.push_back(Bytecode{(uint8_t)opcode, arg});
|
||||
co->iblocks.push_back(curr_block_i);
|
||||
co->lines.push_back(line);
|
||||
@ -108,41 +108,41 @@ namespace pkpy{
|
||||
void CodeEmitContext::emit_store_name(NameScope scope, StrName name, int line){
|
||||
switch(scope){
|
||||
case NAME_LOCAL:
|
||||
emit(OP_STORE_FAST, add_varname(name), line);
|
||||
emit_(OP_STORE_FAST, add_varname(name), line);
|
||||
break;
|
||||
case NAME_GLOBAL:
|
||||
emit(OP_STORE_GLOBAL, StrName(name).index, line);
|
||||
emit_(OP_STORE_GLOBAL, StrName(name).index, line);
|
||||
break;
|
||||
case NAME_GLOBAL_UNKNOWN:
|
||||
emit(OP_STORE_NAME, StrName(name).index, line);
|
||||
emit_(OP_STORE_NAME, StrName(name).index, line);
|
||||
break;
|
||||
default: FATAL_ERROR(); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NameExpr::emit(CodeEmitContext* ctx) {
|
||||
void NameExpr::emit_(CodeEmitContext* ctx) {
|
||||
int index = ctx->co->varnames_inv.try_get(name);
|
||||
if(scope == NAME_LOCAL && index >= 0){
|
||||
ctx->emit(OP_LOAD_FAST, index, line);
|
||||
ctx->emit_(OP_LOAD_FAST, index, line);
|
||||
}else{
|
||||
Opcode op = ctx->level <= 1 ? OP_LOAD_GLOBAL : OP_LOAD_NONLOCAL;
|
||||
// we cannot determine the scope when calling exec()/eval()
|
||||
if(scope == NAME_GLOBAL_UNKNOWN) op = OP_LOAD_NAME;
|
||||
ctx->emit(op, StrName(name).index, line);
|
||||
ctx->emit_(op, StrName(name).index, line);
|
||||
}
|
||||
}
|
||||
|
||||
bool NameExpr::emit_del(CodeEmitContext* ctx) {
|
||||
switch(scope){
|
||||
case NAME_LOCAL:
|
||||
ctx->emit(OP_DELETE_FAST, ctx->add_varname(name), line);
|
||||
ctx->emit_(OP_DELETE_FAST, ctx->add_varname(name), line);
|
||||
break;
|
||||
case NAME_GLOBAL:
|
||||
ctx->emit(OP_DELETE_GLOBAL, StrName(name).index, line);
|
||||
ctx->emit_(OP_DELETE_GLOBAL, StrName(name).index, line);
|
||||
break;
|
||||
case NAME_GLOBAL_UNKNOWN:
|
||||
ctx->emit(OP_DELETE_NAME, StrName(name).index, line);
|
||||
ctx->emit_(OP_DELETE_NAME, StrName(name).index, line);
|
||||
break;
|
||||
default: FATAL_ERROR(); break;
|
||||
}
|
||||
@ -151,21 +151,21 @@ namespace pkpy{
|
||||
|
||||
bool NameExpr::emit_store(CodeEmitContext* ctx) {
|
||||
if(ctx->is_compiling_class){
|
||||
ctx->emit(OP_STORE_CLASS_ATTR, name.index, line);
|
||||
ctx->emit_(OP_STORE_CLASS_ATTR, name.index, line);
|
||||
return true;
|
||||
}
|
||||
ctx->emit_store_name(scope, name, line);
|
||||
return true;
|
||||
}
|
||||
|
||||
void InvertExpr::emit(CodeEmitContext* ctx) {
|
||||
child->emit(ctx);
|
||||
ctx->emit(OP_UNARY_INVERT, BC_NOARG, line);
|
||||
void InvertExpr::emit_(CodeEmitContext* ctx) {
|
||||
child->emit_(ctx);
|
||||
ctx->emit_(OP_UNARY_INVERT, BC_NOARG, line);
|
||||
}
|
||||
|
||||
void StarredExpr::emit(CodeEmitContext* ctx) {
|
||||
child->emit(ctx);
|
||||
ctx->emit(OP_UNARY_STAR, level, line);
|
||||
void StarredExpr::emit_(CodeEmitContext* ctx) {
|
||||
child->emit_(ctx);
|
||||
ctx->emit_(OP_UNARY_STAR, level, line);
|
||||
}
|
||||
|
||||
bool StarredExpr::emit_store(CodeEmitContext* ctx) {
|
||||
@ -174,54 +174,54 @@ namespace pkpy{
|
||||
return child->emit_store(ctx);
|
||||
}
|
||||
|
||||
void NotExpr::emit(CodeEmitContext* ctx) {
|
||||
child->emit(ctx);
|
||||
ctx->emit(OP_UNARY_NOT, BC_NOARG, line);
|
||||
void NotExpr::emit_(CodeEmitContext* ctx) {
|
||||
child->emit_(ctx);
|
||||
ctx->emit_(OP_UNARY_NOT, BC_NOARG, line);
|
||||
}
|
||||
|
||||
void AndExpr::emit(CodeEmitContext* ctx) {
|
||||
lhs->emit(ctx);
|
||||
int patch = ctx->emit(OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, line);
|
||||
rhs->emit(ctx);
|
||||
void AndExpr::emit_(CodeEmitContext* ctx) {
|
||||
lhs->emit_(ctx);
|
||||
int patch = ctx->emit_(OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, line);
|
||||
rhs->emit_(ctx);
|
||||
ctx->patch_jump(patch);
|
||||
}
|
||||
|
||||
void OrExpr::emit(CodeEmitContext* ctx) {
|
||||
lhs->emit(ctx);
|
||||
int patch = ctx->emit(OP_JUMP_IF_TRUE_OR_POP, BC_NOARG, line);
|
||||
rhs->emit(ctx);
|
||||
void OrExpr::emit_(CodeEmitContext* ctx) {
|
||||
lhs->emit_(ctx);
|
||||
int patch = ctx->emit_(OP_JUMP_IF_TRUE_OR_POP, BC_NOARG, line);
|
||||
rhs->emit_(ctx);
|
||||
ctx->patch_jump(patch);
|
||||
}
|
||||
|
||||
void Literal0Expr::emit(CodeEmitContext* ctx){
|
||||
void Literal0Expr::emit_(CodeEmitContext* ctx){
|
||||
switch (token) {
|
||||
case TK("None"): ctx->emit(OP_LOAD_NONE, BC_NOARG, line); break;
|
||||
case TK("True"): ctx->emit(OP_LOAD_TRUE, BC_NOARG, line); break;
|
||||
case TK("False"): ctx->emit(OP_LOAD_FALSE, BC_NOARG, line); break;
|
||||
case TK("..."): ctx->emit(OP_LOAD_ELLIPSIS, BC_NOARG, line); break;
|
||||
case TK("None"): ctx->emit_(OP_LOAD_NONE, BC_NOARG, line); break;
|
||||
case TK("True"): ctx->emit_(OP_LOAD_TRUE, BC_NOARG, line); break;
|
||||
case TK("False"): ctx->emit_(OP_LOAD_FALSE, BC_NOARG, line); break;
|
||||
case TK("..."): ctx->emit_(OP_LOAD_ELLIPSIS, BC_NOARG, line); break;
|
||||
default: FATAL_ERROR();
|
||||
}
|
||||
}
|
||||
|
||||
void LongExpr::emit(CodeEmitContext* ctx) {
|
||||
void LongExpr::emit_(CodeEmitContext* ctx) {
|
||||
VM* vm = ctx->vm;
|
||||
ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(s)), line);
|
||||
ctx->emit(OP_BUILD_LONG, BC_NOARG, line);
|
||||
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(s)), line);
|
||||
ctx->emit_(OP_BUILD_LONG, BC_NOARG, line);
|
||||
}
|
||||
|
||||
void BytesExpr::emit(CodeEmitContext* ctx) {
|
||||
void BytesExpr::emit_(CodeEmitContext* ctx) {
|
||||
VM* vm = ctx->vm;
|
||||
ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(s)), line);
|
||||
ctx->emit(OP_BUILD_BYTES, BC_NOARG, line);
|
||||
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(s)), line);
|
||||
ctx->emit_(OP_BUILD_BYTES, BC_NOARG, line);
|
||||
}
|
||||
|
||||
void LiteralExpr::emit(CodeEmitContext* ctx) {
|
||||
void LiteralExpr::emit_(CodeEmitContext* ctx) {
|
||||
VM* vm = ctx->vm;
|
||||
PyObject* obj = nullptr;
|
||||
if(std::holds_alternative<i64>(value)){
|
||||
i64 _val = std::get<i64>(value);
|
||||
if(_val >= INT16_MIN && _val <= INT16_MAX){
|
||||
ctx->emit(OP_LOAD_INTEGER, (uint16_t)_val, line);
|
||||
ctx->emit_(OP_LOAD_INTEGER, (uint16_t)_val, line);
|
||||
return;
|
||||
}
|
||||
obj = VAR(_val);
|
||||
@ -233,10 +233,10 @@ namespace pkpy{
|
||||
obj = VAR(std::get<Str>(value));
|
||||
}
|
||||
if(obj == nullptr) FATAL_ERROR();
|
||||
ctx->emit(OP_LOAD_CONST, ctx->add_const(obj), line);
|
||||
ctx->emit_(OP_LOAD_CONST, ctx->add_const(obj), line);
|
||||
}
|
||||
|
||||
void NegatedExpr::emit(CodeEmitContext* ctx){
|
||||
void NegatedExpr::emit_(CodeEmitContext* ctx){
|
||||
VM* vm = ctx->vm;
|
||||
// if child is a int of float, do constant folding
|
||||
if(child->is_literal()){
|
||||
@ -244,53 +244,53 @@ namespace pkpy{
|
||||
if(std::holds_alternative<i64>(lit->value)){
|
||||
i64 _val = -std::get<i64>(lit->value);
|
||||
if(_val >= INT16_MIN && _val <= INT16_MAX){
|
||||
ctx->emit(OP_LOAD_INTEGER, (uint16_t)_val, line);
|
||||
ctx->emit_(OP_LOAD_INTEGER, (uint16_t)_val, line);
|
||||
}else{
|
||||
ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(_val)), line);
|
||||
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(_val)), line);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(std::holds_alternative<f64>(lit->value)){
|
||||
PyObject* obj = VAR(-std::get<f64>(lit->value));
|
||||
ctx->emit(OP_LOAD_CONST, ctx->add_const(obj), line);
|
||||
ctx->emit_(OP_LOAD_CONST, ctx->add_const(obj), line);
|
||||
return;
|
||||
}
|
||||
}
|
||||
child->emit(ctx);
|
||||
ctx->emit(OP_UNARY_NEGATIVE, BC_NOARG, line);
|
||||
child->emit_(ctx);
|
||||
ctx->emit_(OP_UNARY_NEGATIVE, BC_NOARG, line);
|
||||
}
|
||||
|
||||
|
||||
void SliceExpr::emit(CodeEmitContext* ctx){
|
||||
void SliceExpr::emit_(CodeEmitContext* ctx){
|
||||
if(start){
|
||||
start->emit(ctx);
|
||||
start->emit_(ctx);
|
||||
}else{
|
||||
ctx->emit(OP_LOAD_NONE, BC_NOARG, line);
|
||||
ctx->emit_(OP_LOAD_NONE, BC_NOARG, line);
|
||||
}
|
||||
|
||||
if(stop){
|
||||
stop->emit(ctx);
|
||||
stop->emit_(ctx);
|
||||
}else{
|
||||
ctx->emit(OP_LOAD_NONE, BC_NOARG, line);
|
||||
ctx->emit_(OP_LOAD_NONE, BC_NOARG, line);
|
||||
}
|
||||
|
||||
if(step){
|
||||
step->emit(ctx);
|
||||
step->emit_(ctx);
|
||||
}else{
|
||||
ctx->emit(OP_LOAD_NONE, BC_NOARG, line);
|
||||
ctx->emit_(OP_LOAD_NONE, BC_NOARG, line);
|
||||
}
|
||||
|
||||
ctx->emit(OP_BUILD_SLICE, BC_NOARG, line);
|
||||
ctx->emit_(OP_BUILD_SLICE, BC_NOARG, line);
|
||||
}
|
||||
|
||||
void DictItemExpr::emit(CodeEmitContext* ctx) {
|
||||
void DictItemExpr::emit_(CodeEmitContext* ctx) {
|
||||
if(is_starred()){
|
||||
PK_ASSERT(key == nullptr);
|
||||
value->emit(ctx);
|
||||
value->emit_(ctx);
|
||||
}else{
|
||||
value->emit(ctx);
|
||||
key->emit(ctx); // reverse order
|
||||
ctx->emit(OP_BUILD_TUPLE, 2, line);
|
||||
value->emit_(ctx);
|
||||
key->emit_(ctx); // reverse order
|
||||
ctx->emit_(OP_BUILD_TUPLE, 2, line);
|
||||
}
|
||||
}
|
||||
|
||||
@ -311,7 +311,7 @@ namespace pkpy{
|
||||
prev.op = OP_NO_OP;
|
||||
prev.arg = BC_NOARG;
|
||||
}else{
|
||||
ctx->emit(OP_UNPACK_SEQUENCE, items.size(), line);
|
||||
ctx->emit_(OP_UNPACK_SEQUENCE, items.size(), line);
|
||||
}
|
||||
}else{
|
||||
// starred assignment target must be in a tuple
|
||||
@ -320,7 +320,7 @@ namespace pkpy{
|
||||
if(starred_i != items.size()-1) return false;
|
||||
// a,*b = [1,2,3]
|
||||
// stack is [1,2,3] -> [1,[2,3]]
|
||||
ctx->emit(OP_UNPACK_EX, items.size()-1, line);
|
||||
ctx->emit_(OP_UNPACK_EX, items.size()-1, line);
|
||||
}
|
||||
// do reverse emit
|
||||
for(int i=items.size()-1; i>=0; i--){
|
||||
@ -338,26 +338,26 @@ namespace pkpy{
|
||||
return true;
|
||||
}
|
||||
|
||||
void CompExpr::emit(CodeEmitContext* ctx){
|
||||
ctx->emit(op0(), 0, line);
|
||||
iter->emit(ctx);
|
||||
ctx->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
|
||||
void CompExpr::emit_(CodeEmitContext* ctx){
|
||||
ctx->emit_(op0(), 0, line);
|
||||
iter->emit_(ctx);
|
||||
ctx->emit_(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
|
||||
ctx->enter_block(FOR_LOOP);
|
||||
ctx->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
|
||||
ctx->emit_(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
|
||||
bool ok = vars->emit_store(ctx);
|
||||
// this error occurs in `vars` instead of this line, but...nevermind
|
||||
PK_ASSERT(ok); // TODO: raise a SyntaxError instead
|
||||
if(cond){
|
||||
cond->emit(ctx);
|
||||
int patch = ctx->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
|
||||
expr->emit(ctx);
|
||||
ctx->emit(op1(), BC_NOARG, BC_KEEPLINE);
|
||||
cond->emit_(ctx);
|
||||
int patch = ctx->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
|
||||
expr->emit_(ctx);
|
||||
ctx->emit_(op1(), BC_NOARG, BC_KEEPLINE);
|
||||
ctx->patch_jump(patch);
|
||||
}else{
|
||||
expr->emit(ctx);
|
||||
ctx->emit(op1(), BC_NOARG, BC_KEEPLINE);
|
||||
expr->emit_(ctx);
|
||||
ctx->emit_(op1(), BC_NOARG, BC_KEEPLINE);
|
||||
}
|
||||
ctx->emit(OP_LOOP_CONTINUE, ctx->get_loop(), BC_KEEPLINE);
|
||||
ctx->emit_(OP_LOOP_CONTINUE, ctx->get_loop(), BC_KEEPLINE);
|
||||
ctx->exit_block();
|
||||
}
|
||||
|
||||
@ -376,24 +376,24 @@ namespace pkpy{
|
||||
if(std::regex_match(expr.str(), pattern)){
|
||||
int dot = expr.index(".");
|
||||
if(dot < 0){
|
||||
ctx->emit(OP_LOAD_NAME, StrName(expr.sv()).index, line);
|
||||
ctx->emit_(OP_LOAD_NAME, StrName(expr.sv()).index, line);
|
||||
}else{
|
||||
StrName name(expr.substr(0, dot).sv());
|
||||
StrName attr(expr.substr(dot+1).sv());
|
||||
ctx->emit(OP_LOAD_NAME, name.index, line);
|
||||
ctx->emit(OP_LOAD_ATTR, attr.index, line);
|
||||
ctx->emit_(OP_LOAD_NAME, name.index, line);
|
||||
ctx->emit_(OP_LOAD_ATTR, attr.index, line);
|
||||
}
|
||||
}else{
|
||||
int index = ctx->add_const(py_var(ctx->vm, expr));
|
||||
ctx->emit(OP_LOAD_CONST, index, line);
|
||||
ctx->emit(OP_EVAL, BC_NOARG, line);
|
||||
ctx->emit_(OP_LOAD_CONST, index, line);
|
||||
ctx->emit_(OP_EVAL, BC_NOARG, line);
|
||||
}
|
||||
if(repr){
|
||||
ctx->emit(OP_REPR, BC_NOARG, line);
|
||||
ctx->emit_(OP_REPR, BC_NOARG, line);
|
||||
}
|
||||
}
|
||||
|
||||
void FStringExpr::emit(CodeEmitContext* ctx){
|
||||
void FStringExpr::emit_(CodeEmitContext* ctx){
|
||||
VM* vm = ctx->vm;
|
||||
PK_LOCAL_STATIC const std::regex pattern(R"(\{(.*?)\})");
|
||||
std::cregex_iterator begin(src.begin(), src.end(), pattern);
|
||||
@ -404,7 +404,7 @@ namespace pkpy{
|
||||
std::cmatch m = *it;
|
||||
if (i < m.position()) {
|
||||
Str literal = src.substr(i, m.position() - i);
|
||||
ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
|
||||
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
|
||||
size++;
|
||||
}
|
||||
Str expr = m[1].str();
|
||||
@ -412,7 +412,7 @@ namespace pkpy{
|
||||
if(conon >= 0){
|
||||
_load_simple_expr(ctx, expr.substr(0, conon));
|
||||
Str spec = expr.substr(conon+1);
|
||||
ctx->emit(OP_FORMAT_STRING, ctx->add_const(VAR(spec)), line);
|
||||
ctx->emit_(OP_FORMAT_STRING, ctx->add_const(VAR(spec)), line);
|
||||
}else{
|
||||
_load_simple_expr(ctx, expr);
|
||||
}
|
||||
@ -421,60 +421,60 @@ namespace pkpy{
|
||||
}
|
||||
if (i < src.length()) {
|
||||
Str literal = src.substr(i, src.length() - i);
|
||||
ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
|
||||
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
|
||||
size++;
|
||||
}
|
||||
ctx->emit(OP_BUILD_STRING, size, line);
|
||||
ctx->emit_(OP_BUILD_STRING, size, line);
|
||||
}
|
||||
|
||||
|
||||
void SubscrExpr::emit(CodeEmitContext* ctx){
|
||||
a->emit(ctx);
|
||||
b->emit(ctx);
|
||||
ctx->emit(OP_LOAD_SUBSCR, BC_NOARG, line);
|
||||
void SubscrExpr::emit_(CodeEmitContext* ctx){
|
||||
a->emit_(ctx);
|
||||
b->emit_(ctx);
|
||||
ctx->emit_(OP_LOAD_SUBSCR, BC_NOARG, line);
|
||||
}
|
||||
|
||||
bool SubscrExpr::emit_del(CodeEmitContext* ctx){
|
||||
a->emit(ctx);
|
||||
b->emit(ctx);
|
||||
ctx->emit(OP_DELETE_SUBSCR, BC_NOARG, line);
|
||||
a->emit_(ctx);
|
||||
b->emit_(ctx);
|
||||
ctx->emit_(OP_DELETE_SUBSCR, BC_NOARG, line);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SubscrExpr::emit_store(CodeEmitContext* ctx){
|
||||
a->emit(ctx);
|
||||
b->emit(ctx);
|
||||
ctx->emit(OP_STORE_SUBSCR, BC_NOARG, line);
|
||||
a->emit_(ctx);
|
||||
b->emit_(ctx);
|
||||
ctx->emit_(OP_STORE_SUBSCR, BC_NOARG, line);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AttribExpr::emit(CodeEmitContext* ctx){
|
||||
a->emit(ctx);
|
||||
void AttribExpr::emit_(CodeEmitContext* ctx){
|
||||
a->emit_(ctx);
|
||||
int index = StrName(b).index;
|
||||
ctx->emit(OP_LOAD_ATTR, index, line);
|
||||
ctx->emit_(OP_LOAD_ATTR, index, line);
|
||||
}
|
||||
|
||||
bool AttribExpr::emit_del(CodeEmitContext* ctx) {
|
||||
a->emit(ctx);
|
||||
a->emit_(ctx);
|
||||
int index = StrName(b).index;
|
||||
ctx->emit(OP_DELETE_ATTR, index, line);
|
||||
ctx->emit_(OP_DELETE_ATTR, index, line);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AttribExpr::emit_store(CodeEmitContext* ctx){
|
||||
a->emit(ctx);
|
||||
a->emit_(ctx);
|
||||
int index = StrName(b).index;
|
||||
ctx->emit(OP_STORE_ATTR, index, line);
|
||||
ctx->emit_(OP_STORE_ATTR, index, line);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AttribExpr::emit_method(CodeEmitContext* ctx) {
|
||||
a->emit(ctx);
|
||||
a->emit_(ctx);
|
||||
int index = StrName(b).index;
|
||||
ctx->emit(OP_LOAD_METHOD, index, line);
|
||||
ctx->emit_(OP_LOAD_METHOD, index, line);
|
||||
}
|
||||
|
||||
void CallExpr::emit(CodeEmitContext* ctx) {
|
||||
void CallExpr::emit_(CodeEmitContext* ctx) {
|
||||
bool vargs = false;
|
||||
bool vkwargs = false;
|
||||
for(auto& arg: args) if(arg->is_starred()) vargs = true;
|
||||
@ -485,43 +485,43 @@ namespace pkpy{
|
||||
auto p = static_cast<AttribExpr*>(callable.get());
|
||||
p->emit_method(ctx); // OP_LOAD_METHOD
|
||||
}else{
|
||||
callable->emit(ctx);
|
||||
ctx->emit(OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
|
||||
callable->emit_(ctx);
|
||||
ctx->emit_(OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
|
||||
}
|
||||
|
||||
if(vargs || vkwargs){
|
||||
for(auto& item: args) item->emit(ctx);
|
||||
ctx->emit(OP_BUILD_TUPLE_UNPACK, (uint16_t)args.size(), line);
|
||||
for(auto& item: args) item->emit_(ctx);
|
||||
ctx->emit_(OP_BUILD_TUPLE_UNPACK, (uint16_t)args.size(), line);
|
||||
|
||||
if(!kwargs.empty()){
|
||||
for(auto& item: kwargs){
|
||||
if(item.second->is_starred()){
|
||||
if(item.second->star_level() != 2) FATAL_ERROR();
|
||||
item.second->emit(ctx);
|
||||
item.second->emit_(ctx);
|
||||
}else{
|
||||
// k=v
|
||||
int index = ctx->add_const(py_var(ctx->vm, item.first));
|
||||
ctx->emit(OP_LOAD_CONST, index, line);
|
||||
item.second->emit(ctx);
|
||||
ctx->emit(OP_BUILD_TUPLE, 2, line);
|
||||
ctx->emit_(OP_LOAD_CONST, index, line);
|
||||
item.second->emit_(ctx);
|
||||
ctx->emit_(OP_BUILD_TUPLE, 2, line);
|
||||
}
|
||||
}
|
||||
ctx->emit(OP_BUILD_DICT_UNPACK, (int)kwargs.size(), line);
|
||||
ctx->emit(OP_CALL_TP, 1, line);
|
||||
ctx->emit_(OP_BUILD_DICT_UNPACK, (int)kwargs.size(), line);
|
||||
ctx->emit_(OP_CALL_TP, 1, line);
|
||||
}else{
|
||||
ctx->emit(OP_CALL_TP, 0, line);
|
||||
ctx->emit_(OP_CALL_TP, 0, line);
|
||||
}
|
||||
}else{
|
||||
// vectorcall protocal
|
||||
for(auto& item: args) item->emit(ctx);
|
||||
for(auto& item: args) item->emit_(ctx);
|
||||
for(auto& item: kwargs){
|
||||
uint16_t index = StrName(item.first.sv()).index;
|
||||
ctx->emit(OP_LOAD_INTEGER, index, line);
|
||||
item.second->emit(ctx);
|
||||
ctx->emit_(OP_LOAD_INTEGER, index, line);
|
||||
item.second->emit_(ctx);
|
||||
}
|
||||
int KWARGC = kwargs.size();
|
||||
int ARGC = args.size();
|
||||
ctx->emit(OP_CALL, (KWARGC<<8)|ARGC, line);
|
||||
ctx->emit_(OP_CALL, (KWARGC<<8)|ARGC, line);
|
||||
}
|
||||
}
|
||||
|
||||
@ -538,26 +538,26 @@ namespace pkpy{
|
||||
if(lhs->is_compare()){
|
||||
static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
|
||||
}else{
|
||||
lhs->emit(ctx); // [a]
|
||||
lhs->emit_(ctx); // [a]
|
||||
}
|
||||
rhs->emit(ctx); // [a, b]
|
||||
ctx->emit(OP_DUP_TOP, BC_NOARG, line); // [a, b, b]
|
||||
ctx->emit(OP_ROT_THREE, BC_NOARG, line); // [b, a, b]
|
||||
rhs->emit_(ctx); // [a, b]
|
||||
ctx->emit_(OP_DUP_TOP, BC_NOARG, line); // [a, b, b]
|
||||
ctx->emit_(OP_ROT_THREE, BC_NOARG, line); // [b, a, b]
|
||||
switch(op){
|
||||
case TK("<"): ctx->emit(OP_COMPARE_LT, BC_NOARG, line); break;
|
||||
case TK("<="): ctx->emit(OP_COMPARE_LE, BC_NOARG, line); break;
|
||||
case TK("=="): ctx->emit(OP_COMPARE_EQ, BC_NOARG, line); break;
|
||||
case TK("!="): ctx->emit(OP_COMPARE_NE, BC_NOARG, line); break;
|
||||
case TK(">"): ctx->emit(OP_COMPARE_GT, BC_NOARG, line); break;
|
||||
case TK(">="): ctx->emit(OP_COMPARE_GE, BC_NOARG, line); break;
|
||||
case TK("<"): ctx->emit_(OP_COMPARE_LT, BC_NOARG, line); break;
|
||||
case TK("<="): ctx->emit_(OP_COMPARE_LE, BC_NOARG, line); break;
|
||||
case TK("=="): ctx->emit_(OP_COMPARE_EQ, BC_NOARG, line); break;
|
||||
case TK("!="): ctx->emit_(OP_COMPARE_NE, BC_NOARG, line); break;
|
||||
case TK(">"): ctx->emit_(OP_COMPARE_GT, BC_NOARG, line); break;
|
||||
case TK(">="): ctx->emit_(OP_COMPARE_GE, BC_NOARG, line); break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
// [b, RES]
|
||||
int index = ctx->emit(OP_SHORTCUT_IF_FALSE_OR_POP, BC_NOARG, line);
|
||||
int index = ctx->emit_(OP_SHORTCUT_IF_FALSE_OR_POP, BC_NOARG, line);
|
||||
jmps.push_back(index);
|
||||
}
|
||||
|
||||
void BinaryExpr::emit(CodeEmitContext* ctx) {
|
||||
void BinaryExpr::emit_(CodeEmitContext* ctx) {
|
||||
std::vector<int> jmps;
|
||||
if(is_compare() && lhs->is_compare()){
|
||||
// (a < b) < c
|
||||
@ -565,51 +565,51 @@ namespace pkpy{
|
||||
// [b, RES]
|
||||
}else{
|
||||
// (1 + 2) < c
|
||||
lhs->emit(ctx);
|
||||
lhs->emit_(ctx);
|
||||
}
|
||||
|
||||
rhs->emit(ctx);
|
||||
rhs->emit_(ctx);
|
||||
switch (op) {
|
||||
case TK("+"): ctx->emit(OP_BINARY_ADD, BC_NOARG, line); break;
|
||||
case TK("-"): ctx->emit(OP_BINARY_SUB, BC_NOARG, line); break;
|
||||
case TK("*"): ctx->emit(OP_BINARY_MUL, BC_NOARG, line); break;
|
||||
case TK("/"): ctx->emit(OP_BINARY_TRUEDIV, BC_NOARG, line); break;
|
||||
case TK("//"): ctx->emit(OP_BINARY_FLOORDIV, BC_NOARG, line); break;
|
||||
case TK("%"): ctx->emit(OP_BINARY_MOD, BC_NOARG, line); break;
|
||||
case TK("**"): ctx->emit(OP_BINARY_POW, BC_NOARG, line); break;
|
||||
case TK("+"): ctx->emit_(OP_BINARY_ADD, BC_NOARG, line); break;
|
||||
case TK("-"): ctx->emit_(OP_BINARY_SUB, BC_NOARG, line); break;
|
||||
case TK("*"): ctx->emit_(OP_BINARY_MUL, BC_NOARG, line); break;
|
||||
case TK("/"): ctx->emit_(OP_BINARY_TRUEDIV, BC_NOARG, line); break;
|
||||
case TK("//"): ctx->emit_(OP_BINARY_FLOORDIV, BC_NOARG, line); break;
|
||||
case TK("%"): ctx->emit_(OP_BINARY_MOD, BC_NOARG, line); break;
|
||||
case TK("**"): ctx->emit_(OP_BINARY_POW, BC_NOARG, line); break;
|
||||
|
||||
case TK("<"): ctx->emit(OP_COMPARE_LT, BC_NOARG, line); break;
|
||||
case TK("<="): ctx->emit(OP_COMPARE_LE, BC_NOARG, line); break;
|
||||
case TK("=="): ctx->emit(OP_COMPARE_EQ, BC_NOARG, line); break;
|
||||
case TK("!="): ctx->emit(OP_COMPARE_NE, BC_NOARG, line); break;
|
||||
case TK(">"): ctx->emit(OP_COMPARE_GT, BC_NOARG, line); break;
|
||||
case TK(">="): ctx->emit(OP_COMPARE_GE, BC_NOARG, line); break;
|
||||
case TK("<"): ctx->emit_(OP_COMPARE_LT, BC_NOARG, line); break;
|
||||
case TK("<="): ctx->emit_(OP_COMPARE_LE, BC_NOARG, line); break;
|
||||
case TK("=="): ctx->emit_(OP_COMPARE_EQ, BC_NOARG, line); break;
|
||||
case TK("!="): ctx->emit_(OP_COMPARE_NE, BC_NOARG, line); break;
|
||||
case TK(">"): ctx->emit_(OP_COMPARE_GT, BC_NOARG, line); break;
|
||||
case TK(">="): ctx->emit_(OP_COMPARE_GE, BC_NOARG, line); break;
|
||||
|
||||
case TK("in"): ctx->emit(OP_CONTAINS_OP, 0, line); break;
|
||||
case TK("not in"): ctx->emit(OP_CONTAINS_OP, 1, line); break;
|
||||
case TK("is"): ctx->emit(OP_IS_OP, 0, line); break;
|
||||
case TK("is not"): ctx->emit(OP_IS_OP, 1, line); break;
|
||||
case TK("in"): ctx->emit_(OP_CONTAINS_OP, 0, line); break;
|
||||
case TK("not in"): ctx->emit_(OP_CONTAINS_OP, 1, line); break;
|
||||
case TK("is"): ctx->emit_(OP_IS_OP, 0, line); break;
|
||||
case TK("is not"): ctx->emit_(OP_IS_OP, 1, line); break;
|
||||
|
||||
case TK("<<"): ctx->emit(OP_BITWISE_LSHIFT, BC_NOARG, line); break;
|
||||
case TK(">>"): ctx->emit(OP_BITWISE_RSHIFT, BC_NOARG, line); break;
|
||||
case TK("&"): ctx->emit(OP_BITWISE_AND, BC_NOARG, line); break;
|
||||
case TK("|"): ctx->emit(OP_BITWISE_OR, BC_NOARG, line); break;
|
||||
case TK("^"): ctx->emit(OP_BITWISE_XOR, BC_NOARG, line); break;
|
||||
case TK("<<"): ctx->emit_(OP_BITWISE_LSHIFT, BC_NOARG, line); break;
|
||||
case TK(">>"): ctx->emit_(OP_BITWISE_RSHIFT, BC_NOARG, line); break;
|
||||
case TK("&"): ctx->emit_(OP_BITWISE_AND, BC_NOARG, line); break;
|
||||
case TK("|"): ctx->emit_(OP_BITWISE_OR, BC_NOARG, line); break;
|
||||
case TK("^"): ctx->emit_(OP_BITWISE_XOR, BC_NOARG, line); break;
|
||||
|
||||
case TK("@"): ctx->emit(OP_BINARY_MATMUL, BC_NOARG, line); break;
|
||||
case TK("@"): ctx->emit_(OP_BINARY_MATMUL, BC_NOARG, line); break;
|
||||
default: FATAL_ERROR();
|
||||
}
|
||||
|
||||
for(int i: jmps) ctx->patch_jump(i);
|
||||
}
|
||||
|
||||
void TernaryExpr::emit(CodeEmitContext* ctx){
|
||||
cond->emit(ctx);
|
||||
int patch = ctx->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, cond->line);
|
||||
true_expr->emit(ctx);
|
||||
int patch_2 = ctx->emit(OP_JUMP_ABSOLUTE, BC_NOARG, true_expr->line);
|
||||
void TernaryExpr::emit_(CodeEmitContext* ctx){
|
||||
cond->emit_(ctx);
|
||||
int patch = ctx->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, cond->line);
|
||||
true_expr->emit_(ctx);
|
||||
int patch_2 = ctx->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, true_expr->line);
|
||||
ctx->patch_jump(patch);
|
||||
false_expr->emit(ctx);
|
||||
false_expr->emit_(ctx);
|
||||
ctx->patch_jump(patch_2);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user