mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-22 20:40:18 +00:00
up
This commit is contained in:
parent
a187e5bcdb
commit
6452acf327
11
src/ceval.h
11
src/ceval.h
@ -38,10 +38,9 @@ __NEXT_STEP:;
|
||||
case OP_LOAD_ELLIPSIS: frame->push(Ellipsis); DISPATCH();
|
||||
case OP_LOAD_BUILTIN_EVAL: frame->push(builtins->attr(m_eval)); DISPATCH();
|
||||
case OP_LOAD_FUNCTION: {
|
||||
PyObject* obj = frame->co->consts[byte.arg];
|
||||
Function f = CAST(Function, obj); // copy it!
|
||||
f._module = frame->_module; // setup module
|
||||
frame->push(VAR(std::move(f)));
|
||||
const FunctionDecl* decl = &frame->co->func_decls[byte.arg];
|
||||
PyObject* obj = VAR(Function({decl, frame->_module, frame->_locals}));
|
||||
frame->push(obj);
|
||||
} DISPATCH();
|
||||
/*****************************************/
|
||||
case OP_LOAD_NAME: {
|
||||
@ -312,10 +311,6 @@ __NEXT_STEP:;
|
||||
/*****************************************/
|
||||
/*****************************************/
|
||||
// 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: {
|
||||
// StrName name = frame->co->names[byte.arg];
|
||||
// PyObject* clsBase = frame->popx();
|
||||
|
@ -60,7 +60,7 @@ struct CodeObject {
|
||||
std::set<StrName> global_names;
|
||||
std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
|
||||
std::map<StrName, int> labels;
|
||||
std::vector<FunctionDecl> functions;
|
||||
std::vector<FunctionDecl> func_decls;
|
||||
|
||||
// may be.. just use a large NameDict?
|
||||
uint32_t perfect_locals_capacity = 2;
|
||||
@ -70,6 +70,10 @@ struct CodeObject {
|
||||
|
||||
void _mark() const {
|
||||
for(PyObject* v : consts) OBJ_MARK(v);
|
||||
for(auto& decl: func_decls){
|
||||
decl.kwargs._mark();
|
||||
decl.code->_mark();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -170,13 +170,13 @@ class Compiler {
|
||||
// PASS
|
||||
void exprLambda(){
|
||||
auto e = make_expr<LambdaExpr>();
|
||||
e->func.name = "<lambda>";
|
||||
e->decl.name = "<lambda>";
|
||||
e->scope = name_scope();
|
||||
if(!match(TK(":"))){
|
||||
_compile_f_args(e->func, false);
|
||||
_compile_f_args(e->decl, false);
|
||||
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
|
||||
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||
pop_context();
|
||||
@ -754,7 +754,7 @@ class Compiler {
|
||||
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
|
||||
do {
|
||||
if(state == 3) SyntaxError("**kwargs should be the last argument");
|
||||
@ -796,7 +796,7 @@ class Compiler {
|
||||
|
||||
void compile_function(){
|
||||
// TODO: bug, if there are multiple decorators, will cause error
|
||||
Function func;
|
||||
FunctionDecl func;
|
||||
StrName obj_name;
|
||||
consume(TK("@id"));
|
||||
func.name = prev().str();
|
||||
@ -816,8 +816,7 @@ class Compiler {
|
||||
func.code = push_context(lexer->src, func.name.str());
|
||||
compile_block_body();
|
||||
pop_context();
|
||||
ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_const(VAR(func)), prev().line);
|
||||
if(name_scope() == NAME_LOCAL) ctx()->emit(OP_SETUP_CLOSURE, BC_NOARG, prev().line);
|
||||
ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_func_decl(func), prev().line);
|
||||
if(!ctx()->is_compiling_class){
|
||||
if(obj_name.empty()){
|
||||
auto e = make_expr<NameExpr>(func.name, name_scope());
|
||||
|
14
src/expr.h
14
src/expr.h
@ -95,6 +95,11 @@ struct CodeEmitContext{
|
||||
co->consts.push_back(v);
|
||||
return co->consts.size() - 1;
|
||||
}
|
||||
|
||||
int add_func_decl(FunctionDecl decl){
|
||||
co->func_decls.push_back(decl);
|
||||
return co->func_decls.size() - 1;
|
||||
}
|
||||
};
|
||||
|
||||
// PASS
|
||||
@ -472,16 +477,13 @@ struct SetCompExpr: CompExpr{
|
||||
};
|
||||
|
||||
struct LambdaExpr: Expr{
|
||||
Function func;
|
||||
FunctionDecl decl;
|
||||
NameScope scope;
|
||||
Str str() const override { return "<lambda>"; }
|
||||
|
||||
void emit(CodeEmitContext* ctx) override {
|
||||
VM* vm = ctx->vm;
|
||||
ctx->emit(OP_LOAD_FUNCTION, ctx->add_const(VAR(func)), line);
|
||||
if(scope == NAME_LOCAL){
|
||||
ctx->emit(OP_SETUP_CLOSURE, BC_NOARG, BC_KEEPLINE);
|
||||
}
|
||||
int index = ctx->add_func_decl(decl);
|
||||
ctx->emit(OP_LOAD_FUNCTION, index, line);
|
||||
}
|
||||
};
|
||||
|
||||
|
2
src/gc.h
2
src/gc.h
@ -130,8 +130,6 @@ template<> inline void _mark<Tuple>(Tuple& t){
|
||||
}
|
||||
|
||||
template<> inline void _mark<Function>(Function& t){
|
||||
t.code->_mark();
|
||||
t.kwargs._mark();
|
||||
if(t._module != nullptr) OBJ_MARK(t._module);
|
||||
if(t._closure != nullptr) t._closure->_mark();
|
||||
}
|
||||
|
@ -42,8 +42,8 @@ struct FunctionDecl {
|
||||
|
||||
struct Function{
|
||||
const FunctionDecl* decl;
|
||||
PyObject* _module = nullptr;
|
||||
NameDict_ _closure = nullptr;
|
||||
PyObject* _module;
|
||||
NameDict_ _closure;
|
||||
};
|
||||
|
||||
struct BoundMethod {
|
||||
|
@ -16,7 +16,6 @@ OPCODE(TRY_BLOCK_EXIT)
|
||||
|
||||
OPCODE(YIELD_VALUE)
|
||||
|
||||
OPCODE(SETUP_CLOSURE)
|
||||
OPCODE(SETUP_DECORATOR)
|
||||
|
||||
OPCODE(BEGIN_CLASS)
|
||||
|
@ -627,7 +627,7 @@ inline void add_module_dis(VM* vm){
|
||||
vm->bind_func<1>(mod, "dis", [](VM* vm, Args& args) {
|
||||
PyObject* f = args[0];
|
||||
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);
|
||||
return vm->None;
|
||||
});
|
||||
|
32
src/vm.h
32
src/vm.h
@ -625,13 +625,9 @@ inline Str VM::disassemble(CodeObject_ co){
|
||||
names << CAST(Str, asRepr(VAR(list)));
|
||||
ss << '\n' << consts.str() << '\n' << names.str();
|
||||
|
||||
for(int i=0; i<co->consts.size(); i++){
|
||||
PyObject* obj = co->consts[i];
|
||||
if(is_type(obj, tp_function)){
|
||||
const auto& f = CAST(Function&, obj);
|
||||
ss << "\n\n" << "Disassembly of " << f.name.str() << ":\n";
|
||||
ss << disassemble(f.code);
|
||||
}
|
||||
for(auto& decl: co->func_decls){
|
||||
ss << "\n\n" << "Disassembly of " << decl.name.str() << ":\n";
|
||||
ss << disassemble(decl.code);
|
||||
}
|
||||
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)){
|
||||
const Function& fn = CAST(Function&, callable);
|
||||
NameDict_ locals = make_sp<NameDict>(
|
||||
fn.code->perfect_locals_capacity,
|
||||
fn.decl->code->perfect_locals_capacity,
|
||||
kLocalsLoadFactor,
|
||||
fn.code->perfect_hash_seed
|
||||
fn.decl->code->perfect_hash_seed
|
||||
);
|
||||
|
||||
int i = 0;
|
||||
for(StrName name : fn.args){
|
||||
for(StrName name : fn.decl->args){
|
||||
if(i < args.size()){
|
||||
locals->set(name, args[i++]);
|
||||
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));
|
||||
}
|
||||
|
||||
locals->update(fn.kwargs);
|
||||
locals->update(fn.decl->kwargs);
|
||||
|
||||
if(!fn.starred_arg.empty()){
|
||||
if(!fn.decl->starred_arg.empty()){
|
||||
List vargs; // handle *args
|
||||
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{
|
||||
for(StrName key : fn.kwargs_order){
|
||||
for(StrName key : fn.decl->kwargs_order){
|
||||
if(i < args.size()){
|
||||
locals->set(key, args[i++]);
|
||||
}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){
|
||||
const Str& key = CAST(Str&, kwargs[i]);
|
||||
if(!fn.kwargs.contains(key)){
|
||||
TypeError(key.escape(true) + " is an invalid keyword argument for " + fn.name.str() + "()");
|
||||
if(!fn.decl->kwargs.contains(key)){
|
||||
TypeError(key.escape(true) + " is an invalid keyword argument for " + fn.decl->name.str() + "()");
|
||||
}
|
||||
locals->set(key, kwargs[i+1]);
|
||||
}
|
||||
PyObject* _module = fn._module != nullptr ? fn._module : top_frame()->_module;
|
||||
auto _frame = _new_frame(fn.code, _module, locals, fn._closure);
|
||||
if(fn.code->is_generator) return PyIter(Generator(this, std::move(_frame)));
|
||||
auto _frame = _new_frame(fn.decl->code, _module, locals, fn._closure);
|
||||
if(fn.decl->code->is_generator) return PyIter(Generator(this, std::move(_frame)));
|
||||
callstack.push(std::move(_frame));
|
||||
if(opCall) return _py_op_call;
|
||||
return _exec();
|
||||
|
Loading…
x
Reference in New Issue
Block a user