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_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();
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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());
|
||||||
|
14
src/expr.h
14
src/expr.h
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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){
|
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();
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
});
|
});
|
||||||
|
32
src/vm.h
32
src/vm.h
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user