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