mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 12:00:18 +00:00
fix a bug
This commit is contained in:
parent
6452acf327
commit
9077da4d6c
@ -15,7 +15,7 @@ __NEXT_STEP:;
|
|||||||
* For example, frame->popx() returns a strong reference which may be dangerous
|
* For example, frame->popx() returns a strong reference which may be dangerous
|
||||||
* `Args` containing strong references is safe if it is passed to `call` or `fast_call`
|
* `Args` containing strong references is safe if it is passed to `call` or `fast_call`
|
||||||
*/
|
*/
|
||||||
heap._auto_collect(this);
|
//heap._auto_collect(this);
|
||||||
|
|
||||||
const Bytecode& byte = frame->next_bytecode();
|
const Bytecode& byte = frame->next_bytecode();
|
||||||
switch (byte.op)
|
switch (byte.op)
|
||||||
@ -38,7 +38,7 @@ __NEXT_STEP:;
|
|||||||
case OP_LOAD_ELLIPSIS: frame->push(Ellipsis); DISPATCH();
|
case OP_LOAD_ELLIPSIS: frame->push(Ellipsis); DISPATCH();
|
||||||
case OP_LOAD_BUILTIN_EVAL: frame->push(builtins->attr(m_eval)); DISPATCH();
|
case OP_LOAD_BUILTIN_EVAL: frame->push(builtins->attr(m_eval)); DISPATCH();
|
||||||
case OP_LOAD_FUNCTION: {
|
case OP_LOAD_FUNCTION: {
|
||||||
const FunctionDecl* decl = &frame->co->func_decls[byte.arg];
|
FuncDecl_ decl = frame->co->func_decls[byte.arg];
|
||||||
PyObject* obj = VAR(Function({decl, frame->_module, frame->_locals}));
|
PyObject* obj = VAR(Function({decl, frame->_module, frame->_locals}));
|
||||||
frame->push(obj);
|
frame->push(obj);
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
|
@ -60,7 +60,7 @@ struct CodeObject {
|
|||||||
std::set<StrName> global_names;
|
std::set<StrName> global_names;
|
||||||
std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
|
std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
|
||||||
std::map<StrName, int> labels;
|
std::map<StrName, int> labels;
|
||||||
std::vector<FunctionDecl> func_decls;
|
std::vector<FuncDecl_> func_decls;
|
||||||
|
|
||||||
// may be.. just use a large NameDict?
|
// may be.. just use a large NameDict?
|
||||||
uint32_t perfect_locals_capacity = 2;
|
uint32_t perfect_locals_capacity = 2;
|
||||||
@ -71,8 +71,8 @@ struct CodeObject {
|
|||||||
void _mark() const {
|
void _mark() const {
|
||||||
for(PyObject* v : consts) OBJ_MARK(v);
|
for(PyObject* v : consts) OBJ_MARK(v);
|
||||||
for(auto& decl: func_decls){
|
for(auto& decl: func_decls){
|
||||||
decl.kwargs._mark();
|
decl->kwargs._mark();
|
||||||
decl.code->_mark();
|
decl->code->_mark();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -169,14 +169,12 @@ class Compiler {
|
|||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprLambda(){
|
void exprLambda(){
|
||||||
auto e = make_expr<LambdaExpr>();
|
auto e = make_expr<LambdaExpr>(name_scope());
|
||||||
e->decl.name = "<lambda>";
|
|
||||||
e->scope = name_scope();
|
|
||||||
if(!match(TK(":"))){
|
if(!match(TK(":"))){
|
||||||
_compile_f_args(e->decl, false);
|
_compile_f_args(e->decl, false);
|
||||||
consume(TK(":"));
|
consume(TK(":"));
|
||||||
}
|
}
|
||||||
e->decl.code = push_context(lexer->src, "<lambda>");
|
e->decl->code = push_context(lexer->src, e->decl->name.str());
|
||||||
EXPR(false); // https://github.com/blueloveTH/pocketpy/issues/37
|
EXPR(false); // https://github.com/blueloveTH/pocketpy/issues/37
|
||||||
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||||
pop_context();
|
pop_context();
|
||||||
@ -754,7 +752,7 @@ class Compiler {
|
|||||||
ctx()->emit(OP_END_CLASS, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit(OP_END_CLASS, BC_NOARG, BC_KEEPLINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _compile_f_args(FunctionDecl& func, bool enable_type_hints){
|
void _compile_f_args(FuncDecl_ decl, bool enable_type_hints){
|
||||||
int state = 0; // 0 for args, 1 for *args, 2 for k=v, 3 for **kwargs
|
int state = 0; // 0 for args, 1 for *args, 2 for k=v, 3 for **kwargs
|
||||||
do {
|
do {
|
||||||
if(state == 3) SyntaxError("**kwargs should be the last argument");
|
if(state == 3) SyntaxError("**kwargs should be the last argument");
|
||||||
@ -769,7 +767,7 @@ class Compiler {
|
|||||||
|
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
const Str& name = prev().str();
|
const Str& name = prev().str();
|
||||||
if(func.has_name(name)) SyntaxError("duplicate argument name");
|
if(decl->has_name(name)) SyntaxError("duplicate argument name");
|
||||||
|
|
||||||
// eat type hints
|
// eat type hints
|
||||||
if(enable_type_hints && match(TK(":"))) consume(TK("@id"));
|
if(enable_type_hints && match(TK(":"))) consume(TK("@id"));
|
||||||
@ -778,16 +776,16 @@ class Compiler {
|
|||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case 0: func.args.push_back(name); break;
|
case 0: decl->args.push_back(name); break;
|
||||||
case 1: func.starred_arg = name; state+=1; break;
|
case 1: decl->starred_arg = name; state+=1; break;
|
||||||
case 2: {
|
case 2: {
|
||||||
consume(TK("="));
|
consume(TK("="));
|
||||||
PyObject* value = read_literal();
|
PyObject* value = read_literal();
|
||||||
if(value == nullptr){
|
if(value == nullptr){
|
||||||
SyntaxError(Str("expect a literal, not ") + TK_STR(curr().type));
|
SyntaxError(Str("expect a literal, not ") + TK_STR(curr().type));
|
||||||
}
|
}
|
||||||
func.kwargs.set(name, value);
|
decl->kwargs.set(name, value);
|
||||||
func.kwargs_order.push_back(name);
|
decl->kwargs_order.push_back(name);
|
||||||
} break;
|
} break;
|
||||||
case 3: SyntaxError("**kwargs is not supported yet"); break;
|
case 3: SyntaxError("**kwargs is not supported yet"); break;
|
||||||
}
|
}
|
||||||
@ -796,38 +794,38 @@ class Compiler {
|
|||||||
|
|
||||||
void compile_function(){
|
void compile_function(){
|
||||||
// TODO: bug, if there are multiple decorators, will cause error
|
// TODO: bug, if there are multiple decorators, will cause error
|
||||||
FunctionDecl func;
|
FuncDecl_ decl = make_sp<FuncDecl>();
|
||||||
StrName obj_name;
|
StrName obj_name;
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
func.name = prev().str();
|
decl->name = prev().str();
|
||||||
if(!ctx()->is_compiling_class && match(TK("::"))){
|
if(!ctx()->is_compiling_class && match(TK("::"))){
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
obj_name = func.name;
|
obj_name = decl->name;
|
||||||
func.name = prev().str();
|
decl->name = prev().str();
|
||||||
}
|
}
|
||||||
consume(TK("("));
|
consume(TK("("));
|
||||||
if (!match(TK(")"))) {
|
if (!match(TK(")"))) {
|
||||||
_compile_f_args(func, true);
|
_compile_f_args(decl, true);
|
||||||
consume(TK(")"));
|
consume(TK(")"));
|
||||||
}
|
}
|
||||||
if(match(TK("->"))){
|
if(match(TK("->"))){
|
||||||
if(!match(TK("None"))) consume(TK("@id"));
|
if(!match(TK("None"))) consume(TK("@id"));
|
||||||
}
|
}
|
||||||
func.code = push_context(lexer->src, func.name.str());
|
decl->code = push_context(lexer->src, decl->name.str());
|
||||||
compile_block_body();
|
compile_block_body();
|
||||||
pop_context();
|
pop_context();
|
||||||
ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_func_decl(func), prev().line);
|
ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_func_decl(decl), prev().line);
|
||||||
if(!ctx()->is_compiling_class){
|
if(!ctx()->is_compiling_class){
|
||||||
if(obj_name.empty()){
|
if(obj_name.empty()){
|
||||||
auto e = make_expr<NameExpr>(func.name, name_scope());
|
auto e = make_expr<NameExpr>(decl->name, name_scope());
|
||||||
e->emit_store(ctx());
|
e->emit_store(ctx());
|
||||||
} else {
|
} else {
|
||||||
ctx()->emit(OP_LOAD_NAME, ctx()->add_name(obj_name), prev().line);
|
ctx()->emit(OP_LOAD_NAME, ctx()->add_name(obj_name), prev().line);
|
||||||
int index = ctx()->add_name(func.name);
|
int index = ctx()->add_name(decl->name);
|
||||||
ctx()->emit(OP_STORE_ATTR, index, prev().line);
|
ctx()->emit(OP_STORE_ATTR, index, prev().line);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
ctx()->emit(OP_STORE_CLASS_ATTR, ctx()->add_name(func.name), BC_KEEPLINE);
|
ctx()->emit(OP_STORE_CLASS_ATTR, ctx()->add_name(decl->name), BC_KEEPLINE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
src/expr.h
10
src/expr.h
@ -96,7 +96,7 @@ struct CodeEmitContext{
|
|||||||
return co->consts.size() - 1;
|
return co->consts.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int add_func_decl(FunctionDecl decl){
|
int add_func_decl(FuncDecl_ decl){
|
||||||
co->func_decls.push_back(decl);
|
co->func_decls.push_back(decl);
|
||||||
return co->func_decls.size() - 1;
|
return co->func_decls.size() - 1;
|
||||||
}
|
}
|
||||||
@ -477,9 +477,15 @@ struct SetCompExpr: CompExpr{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct LambdaExpr: Expr{
|
struct LambdaExpr: Expr{
|
||||||
FunctionDecl decl;
|
FuncDecl_ decl;
|
||||||
NameScope scope;
|
NameScope scope;
|
||||||
Str str() const override { return "<lambda>"; }
|
Str str() const override { return "<lambda>"; }
|
||||||
|
|
||||||
|
LambdaExpr(NameScope scope){
|
||||||
|
this->decl = make_sp<FuncDecl>();
|
||||||
|
this->decl->name = "<lambda>";
|
||||||
|
this->scope = scope;
|
||||||
|
}
|
||||||
|
|
||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
int index = ctx->add_func_decl(decl);
|
int index = ctx->add_func_decl(decl);
|
||||||
|
@ -24,7 +24,7 @@ struct NativeFunc {
|
|||||||
PyObject* operator()(VM* vm, Args& args) const;
|
PyObject* operator()(VM* vm, Args& args) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FunctionDecl {
|
struct FuncDecl {
|
||||||
StrName name;
|
StrName name;
|
||||||
CodeObject_ code;
|
CodeObject_ code;
|
||||||
std::vector<StrName> args;
|
std::vector<StrName> args;
|
||||||
@ -40,8 +40,10 @@ struct FunctionDecl {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using FuncDecl_ = shared_ptr<FuncDecl>;
|
||||||
|
|
||||||
struct Function{
|
struct Function{
|
||||||
const FunctionDecl* decl;
|
FuncDecl_ decl;
|
||||||
PyObject* _module;
|
PyObject* _module;
|
||||||
NameDict_ _closure;
|
NameDict_ _closure;
|
||||||
};
|
};
|
||||||
|
4
src/vm.h
4
src/vm.h
@ -626,8 +626,8 @@ inline Str VM::disassemble(CodeObject_ co){
|
|||||||
ss << '\n' << consts.str() << '\n' << names.str();
|
ss << '\n' << consts.str() << '\n' << names.str();
|
||||||
|
|
||||||
for(auto& decl: co->func_decls){
|
for(auto& decl: co->func_decls){
|
||||||
ss << "\n\n" << "Disassembly of " << decl.name.str() << ":\n";
|
ss << "\n\n" << "Disassembly of " << decl->name.str() << ":\n";
|
||||||
ss << disassemble(decl.code);
|
ss << disassemble(decl->code);
|
||||||
}
|
}
|
||||||
return Str(ss.str());
|
return Str(ss.str());
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user