This commit is contained in:
blueloveTH 2023-04-05 13:57:40 +08:00
parent a187e5bcdb
commit 6452acf327
9 changed files with 39 additions and 46 deletions

View File

@ -38,10 +38,9 @@ __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: {
PyObject* obj = frame->co->consts[byte.arg]; const FunctionDecl* decl = &frame->co->func_decls[byte.arg];
Function f = CAST(Function, obj); // copy it! PyObject* obj = VAR(Function({decl, frame->_module, frame->_locals}));
f._module = frame->_module; // setup module frame->push(obj);
frame->push(VAR(std::move(f)));
} DISPATCH(); } DISPATCH();
/*****************************************/ /*****************************************/
case OP_LOAD_NAME: { case OP_LOAD_NAME: {
@ -312,10 +311,6 @@ __NEXT_STEP:;
/*****************************************/ /*****************************************/
/*****************************************/ /*****************************************/
// case OP_SETUP_DECORATOR: DISPATCH(); // case OP_SETUP_DECORATOR: DISPATCH();
// case OP_SETUP_CLOSURE: {
// Function& f = CAST(Function&, frame->top()); // reference
// f._closure = frame->_locals;
// } DISPATCH();
// case OP_BEGIN_CLASS: { // case OP_BEGIN_CLASS: {
// StrName name = frame->co->names[byte.arg]; // StrName name = frame->co->names[byte.arg];
// PyObject* clsBase = frame->popx(); // PyObject* clsBase = frame->popx();

View File

@ -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> functions; std::vector<FunctionDecl> 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;
@ -70,6 +70,10 @@ 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){
decl.kwargs._mark();
decl.code->_mark();
}
} }
}; };

View File

@ -170,13 +170,13 @@ class Compiler {
// PASS // PASS
void exprLambda(){ void exprLambda(){
auto e = make_expr<LambdaExpr>(); auto e = make_expr<LambdaExpr>();
e->func.name = "<lambda>"; e->decl.name = "<lambda>";
e->scope = name_scope(); e->scope = name_scope();
if(!match(TK(":"))){ if(!match(TK(":"))){
_compile_f_args(e->func, false); _compile_f_args(e->decl, false);
consume(TK(":")); consume(TK(":"));
} }
e->func.code = push_context(lexer->src, "<lambda>"); e->decl.code = push_context(lexer->src, "<lambda>");
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 +754,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(Function& func, bool enable_type_hints){ void _compile_f_args(FunctionDecl& func, 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");
@ -796,7 +796,7 @@ 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
Function func; FunctionDecl func;
StrName obj_name; StrName obj_name;
consume(TK("@id")); consume(TK("@id"));
func.name = prev().str(); func.name = prev().str();
@ -816,8 +816,7 @@ class Compiler {
func.code = push_context(lexer->src, func.name.str()); func.code = push_context(lexer->src, func.name.str());
compile_block_body(); compile_block_body();
pop_context(); pop_context();
ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_const(VAR(func)), prev().line); ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_func_decl(func), prev().line);
if(name_scope() == NAME_LOCAL) ctx()->emit(OP_SETUP_CLOSURE, BC_NOARG, 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>(func.name, name_scope());

View File

@ -95,6 +95,11 @@ struct CodeEmitContext{
co->consts.push_back(v); co->consts.push_back(v);
return co->consts.size() - 1; return co->consts.size() - 1;
} }
int add_func_decl(FunctionDecl decl){
co->func_decls.push_back(decl);
return co->func_decls.size() - 1;
}
}; };
// PASS // PASS
@ -472,16 +477,13 @@ struct SetCompExpr: CompExpr{
}; };
struct LambdaExpr: Expr{ struct LambdaExpr: Expr{
Function func; FunctionDecl decl;
NameScope scope; NameScope scope;
Str str() const override { return "<lambda>"; } Str str() const override { return "<lambda>"; }
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {
VM* vm = ctx->vm; int index = ctx->add_func_decl(decl);
ctx->emit(OP_LOAD_FUNCTION, ctx->add_const(VAR(func)), line); ctx->emit(OP_LOAD_FUNCTION, index, line);
if(scope == NAME_LOCAL){
ctx->emit(OP_SETUP_CLOSURE, BC_NOARG, BC_KEEPLINE);
}
} }
}; };

View File

@ -130,8 +130,6 @@ template<> inline void _mark<Tuple>(Tuple& t){
} }
template<> inline void _mark<Function>(Function& t){ template<> inline void _mark<Function>(Function& t){
t.code->_mark();
t.kwargs._mark();
if(t._module != nullptr) OBJ_MARK(t._module); if(t._module != nullptr) OBJ_MARK(t._module);
if(t._closure != nullptr) t._closure->_mark(); if(t._closure != nullptr) t._closure->_mark();
} }

View File

@ -42,8 +42,8 @@ struct FunctionDecl {
struct Function{ struct Function{
const FunctionDecl* decl; const FunctionDecl* decl;
PyObject* _module = nullptr; PyObject* _module;
NameDict_ _closure = nullptr; NameDict_ _closure;
}; };
struct BoundMethod { struct BoundMethod {

View File

@ -16,7 +16,6 @@ OPCODE(TRY_BLOCK_EXIT)
OPCODE(YIELD_VALUE) OPCODE(YIELD_VALUE)
OPCODE(SETUP_CLOSURE)
OPCODE(SETUP_DECORATOR) OPCODE(SETUP_DECORATOR)
OPCODE(BEGIN_CLASS) OPCODE(BEGIN_CLASS)

View File

@ -627,7 +627,7 @@ inline void add_module_dis(VM* vm){
vm->bind_func<1>(mod, "dis", [](VM* vm, Args& args) { vm->bind_func<1>(mod, "dis", [](VM* vm, Args& args) {
PyObject* f = args[0]; PyObject* f = args[0];
if(is_type(f, vm->tp_bound_method)) f = CAST(BoundMethod, args[0]).method; if(is_type(f, vm->tp_bound_method)) f = CAST(BoundMethod, args[0]).method;
CodeObject_ code = CAST(Function, f).code; CodeObject_ code = CAST(Function&, f).decl->code;
(*vm->_stdout) << vm->disassemble(code); (*vm->_stdout) << vm->disassemble(code);
return vm->None; return vm->None;
}); });

View File

@ -625,13 +625,9 @@ inline Str VM::disassemble(CodeObject_ co){
names << CAST(Str, asRepr(VAR(list))); names << CAST(Str, asRepr(VAR(list)));
ss << '\n' << consts.str() << '\n' << names.str(); ss << '\n' << consts.str() << '\n' << names.str();
for(int i=0; i<co->consts.size(); i++){ for(auto& decl: co->func_decls){
PyObject* obj = co->consts[i]; ss << "\n\n" << "Disassembly of " << decl.name.str() << ":\n";
if(is_type(obj, tp_function)){ ss << disassemble(decl.code);
const auto& f = CAST(Function&, obj);
ss << "\n\n" << "Disassembly of " << f.name.str() << ":\n";
ss << disassemble(f.code);
}
} }
return Str(ss.str()); return Str(ss.str());
} }
@ -718,13 +714,13 @@ inline PyObject* VM::call(PyObject* callable, Args args, const Args& kwargs, boo
} else if(is_type(callable, tp_function)){ } else if(is_type(callable, tp_function)){
const Function& fn = CAST(Function&, callable); const Function& fn = CAST(Function&, callable);
NameDict_ locals = make_sp<NameDict>( NameDict_ locals = make_sp<NameDict>(
fn.code->perfect_locals_capacity, fn.decl->code->perfect_locals_capacity,
kLocalsLoadFactor, kLocalsLoadFactor,
fn.code->perfect_hash_seed fn.decl->code->perfect_hash_seed
); );
int i = 0; int i = 0;
for(StrName name : fn.args){ for(StrName name : fn.decl->args){
if(i < args.size()){ if(i < args.size()){
locals->set(name, args[i++]); locals->set(name, args[i++]);
continue; continue;
@ -732,14 +728,14 @@ inline PyObject* VM::call(PyObject* callable, Args args, const Args& kwargs, boo
TypeError("missing positional argument " + name.str().escape(true)); TypeError("missing positional argument " + name.str().escape(true));
} }
locals->update(fn.kwargs); locals->update(fn.decl->kwargs);
if(!fn.starred_arg.empty()){ if(!fn.decl->starred_arg.empty()){
List vargs; // handle *args List vargs; // handle *args
while(i < args.size()) vargs.push_back(args[i++]); while(i < args.size()) vargs.push_back(args[i++]);
locals->set(fn.starred_arg, VAR(Tuple(std::move(vargs)))); locals->set(fn.decl->starred_arg, VAR(Tuple(std::move(vargs))));
}else{ }else{
for(StrName key : fn.kwargs_order){ for(StrName key : fn.decl->kwargs_order){
if(i < args.size()){ if(i < args.size()){
locals->set(key, args[i++]); locals->set(key, args[i++]);
}else{ }else{
@ -751,14 +747,14 @@ inline PyObject* VM::call(PyObject* callable, Args args, const Args& kwargs, boo
for(int i=0; i<kwargs.size(); i+=2){ for(int i=0; i<kwargs.size(); i+=2){
const Str& key = CAST(Str&, kwargs[i]); const Str& key = CAST(Str&, kwargs[i]);
if(!fn.kwargs.contains(key)){ if(!fn.decl->kwargs.contains(key)){
TypeError(key.escape(true) + " is an invalid keyword argument for " + fn.name.str() + "()"); TypeError(key.escape(true) + " is an invalid keyword argument for " + fn.decl->name.str() + "()");
} }
locals->set(key, kwargs[i+1]); locals->set(key, kwargs[i+1]);
} }
PyObject* _module = fn._module != nullptr ? fn._module : top_frame()->_module; PyObject* _module = fn._module != nullptr ? fn._module : top_frame()->_module;
auto _frame = _new_frame(fn.code, _module, locals, fn._closure); auto _frame = _new_frame(fn.decl->code, _module, locals, fn._closure);
if(fn.code->is_generator) return PyIter(Generator(this, std::move(_frame))); if(fn.decl->code->is_generator) return PyIter(Generator(this, std::move(_frame)));
callstack.push(std::move(_frame)); callstack.push(std::move(_frame));
if(opCall) return _py_op_call; if(opCall) return _py_op_call;
return _exec(); return _exec();