Compare commits

..

No commits in common. "651bf997fc566ef8ba2f23f08aa9e625315cc26e" and "ad1482370b9c99a9b54bb7d3dc4369a72480e41e" have entirely different histories.

14 changed files with 124 additions and 430 deletions

View File

@ -36,19 +36,17 @@ typedef struct Frame {
const Bytecode* ip; const Bytecode* ip;
const CodeObject* co; const CodeObject* co;
py_GlobalRef module; py_GlobalRef module;
py_StackRef p0; // unwinding base bool has_function; // is p0 a function?
py_StackRef locals; // locals base py_StackRef p0; // unwinding base
bool has_function; // is p0 a function? py_StackRef locals; // locals base
bool is_dynamic; // is dynamic frame?
UnwindTarget* uw_list; UnwindTarget* uw_list;
} Frame; } Frame;
Frame* Frame__new(const CodeObject* co, Frame* Frame__new(const CodeObject* co,
py_GlobalRef module, py_GlobalRef module,
py_StackRef p0,
py_StackRef locals,
bool has_function, bool has_function,
bool is_dynamic); py_StackRef p0,
py_StackRef locals);
void Frame__delete(Frame* self); void Frame__delete(Frame* self);
int Frame__ip(const Frame* self); int Frame__ip(const Frame* self);

View File

@ -46,6 +46,7 @@ typedef struct VM {
py_TValue reg[8]; // users' registers py_TValue reg[8]; // users' registers
py_TValue* __curr_class; py_TValue* __curr_class;
FuncDecl_ __dynamic_func_decl;
py_TValue __vectorcall_buffer[PK_MAX_CO_VARNAMES]; py_TValue __vectorcall_buffer[PK_MAX_CO_VARNAMES];
ManagedHeap heap; ManagedHeap heap;
@ -125,11 +126,5 @@ py_Type pk_property__register();
py_Type pk_staticmethod__register(); py_Type pk_staticmethod__register();
py_Type pk_classmethod__register(); py_Type pk_classmethod__register();
py_Type pk_generator__register(); py_Type pk_generator__register();
py_Type pk_namedict__register();
py_Type pk_locals__register();
py_TValue pk_builtins__register(); py_TValue pk_builtins__register();
/* mappingproxy */
void pk_mappingproxy__namedict(py_Ref out, py_Ref object);
void pk_mappingproxy__locals(py_Ref out, Frame* frame);

View File

@ -75,15 +75,6 @@ bool py_exec(const char* source,
enum py_CompileMode mode, enum py_CompileMode mode,
py_Ref module) PY_RAISE; py_Ref module) PY_RAISE;
/// Run a source string in dynamic mode.
/// Assume `globals()` and `locals()` are pushed to the stack.
/// After the execution, the result will be set to `py_retval()`.
/// The stack size will be reduced by 2.
bool py_execdyn(const char* source,
const char* filename,
enum py_CompileMode mode,
py_Ref module) PY_RAISE;
/************* Values Creation *************/ /************* Values Creation *************/
/// Create an `int` object. /// Create an `int` object.
@ -526,8 +517,7 @@ enum py_PredefinedTypes {
tp_BaseException, // 2 slots (arg + inner exc) tp_BaseException, // 2 slots (arg + inner exc)
tp_Exception, tp_Exception,
tp_bytes, tp_bytes,
tp_namedict, tp_mappingproxy,
tp_locals,
tp_dict, tp_dict,
tp_dict_items, // 1 slot tp_dict_items, // 1 slot
tp_property, // 2 slots (getter + setter) tp_property, // 2 slots (getter + setter)

View File

@ -1,3 +1,4 @@
from pkpy import _enable_instance_dict
from typing import Generic, TypeVar, Iterable from typing import Generic, TypeVar, Iterable
T = TypeVar('T') T = TypeVar('T')

View File

@ -1833,10 +1833,7 @@ static Error* exprName(Compiler* self) {
py_Name name = py_namev(Token__sv(prev())); py_Name name = py_namev(Token__sv(prev()));
NameScope scope = name_scope(self); NameScope scope = name_scope(self);
// promote this name to global scope if needed // promote this name to global scope if needed
if(c11_smallmap_n2i__contains(&ctx()->global_names, name)) { if(c11_smallmap_n2i__contains(&ctx()->global_names, name)) { scope = NAME_GLOBAL; }
if(scope == NAME_GLOBAL_UNKNOWN) return SyntaxError(self, "cannot use global keyword here");
scope = NAME_GLOBAL;
}
NameExpr* e = NameExpr__new(prev()->line, name, scope); NameExpr* e = NameExpr__new(prev()->line, name, scope);
Ctx__s_push(ctx(), (Expr*)e); Ctx__s_push(ctx(), (Expr*)e);
return NULL; return NULL;

View File

@ -159,65 +159,28 @@ FrameResult VM__run_top_frame(VM* self) {
} }
case OP_LOAD_NAME: { case OP_LOAD_NAME: {
py_Name name = byte.arg; py_Name name = byte.arg;
py_TValue* tmp; py_Ref tmp = Frame__f_locals_try_get(frame, name);
if(!frame->is_dynamic) { if(tmp != NULL) {
// locals if(py_isnil(tmp)) {
tmp = Frame__f_locals_try_get(frame, name); UnboundLocalError(name);
if(tmp != NULL) { goto __ERROR;
if(py_isnil(tmp)) {
UnboundLocalError(name);
goto __ERROR;
}
PUSH(tmp);
DISPATCH();
}
// closure
tmp = Frame__f_closure_try_get(frame, name);
if(tmp != NULL) {
PUSH(tmp);
DISPATCH();
}
// globals
tmp = py_getdict(frame->module, name);
if(tmp != NULL) {
PUSH(tmp);
DISPATCH();
}
} else {
py_newstr(SP()++, py_name2str(name));
// locals
if(py_getitem(&frame->p0[1], TOP())) {
py_assign(TOP(), py_retval());
DISPATCH();
} else {
if(py_matchexc(tp_KeyError)) {
py_clearexc(NULL);
} else {
goto __ERROR;
}
}
// closure
tmp = Frame__f_closure_try_get(frame, name);
if(tmp != NULL) {
py_assign(TOP(), tmp);
DISPATCH();
}
// globals
if(py_getitem(&frame->p0[0], TOP())) {
py_assign(TOP(), py_retval());
DISPATCH();
} else {
if(py_matchexc(tp_KeyError)) {
py_clearexc(NULL);
} else {
goto __ERROR;
}
} }
PUSH(tmp);
DISPATCH();
}
tmp = Frame__f_closure_try_get(frame, name);
if(tmp != NULL) {
PUSH(tmp);
DISPATCH();
}
tmp = py_getdict(frame->module, name);
if(tmp != NULL) {
PUSH(tmp);
DISPATCH();
} }
// builtins
tmp = py_getdict(&self->builtins, name); tmp = py_getdict(&self->builtins, name);
if(tmp != NULL) { if(tmp != NULL) {
py_assign(TOP(), tmp); PUSH(tmp);
DISPATCH(); DISPATCH();
} }
NameError(name); NameError(name);
@ -321,35 +284,25 @@ FrameResult VM__run_top_frame(VM* self) {
} }
case OP_STORE_FAST: frame->locals[byte.arg] = POPX(); DISPATCH(); case OP_STORE_FAST: frame->locals[byte.arg] = POPX(); DISPATCH();
case OP_STORE_NAME: { case OP_STORE_NAME: {
assert(frame->is_dynamic);
py_Name name = byte.arg; py_Name name = byte.arg;
py_newstr(SP()++, py_name2str(name)); if(frame->has_function) {
// [value, name] py_Ref slot = Frame__f_locals_try_get(frame, name);
if(!py_isnone(&frame->p0[1])){ if(slot != NULL) {
// locals *slot = *TOP(); // store in locals if possible
if(py_setitem(&frame->p0[1], TOP(), SECOND())) {
STACK_SHRINK(2);
DISPATCH();
} else { } else {
if(py_matchexc(tp_KeyError)) { // Function& func = frame->_callable->as<Function>();
py_clearexc(NULL); // if(func.decl == __dynamic_func_decl) {
NameError(name); // assert(func._closure != nullptr);
} // func._closure->set(_name, _0);
goto __ERROR; // } else {
} // NameError(_name);
}else{ // goto __ERROR;
// globals // }
if(py_setitem(&frame->p0[0], TOP(), SECOND())) {
STACK_SHRINK(2);
DISPATCH();
} else {
if(py_matchexc(tp_KeyError)) {
py_clearexc(NULL);
NameError(name);
}
goto __ERROR;
} }
} else {
py_setdict(frame->module, name, TOP());
} }
POP();
DISPATCH(); DISPATCH();
} }
case OP_STORE_GLOBAL: { case OP_STORE_GLOBAL: {
@ -392,31 +345,25 @@ FrameResult VM__run_top_frame(VM* self) {
DISPATCH(); DISPATCH();
} }
case OP_DELETE_NAME: { case OP_DELETE_NAME: {
assert(frame->is_dynamic);
py_Name name = byte.arg; py_Name name = byte.arg;
py_newstr(SP()++, py_name2str(name)); if(frame->has_function) {
if(!py_isnone(&frame->p0[1])){ py_TValue* slot = Frame__f_locals_try_get(frame, name);
// locals if(slot) {
if(py_delitem(&frame->p0[1], TOP())) { py_newnil(slot);
POP();
DISPATCH();
} else { } else {
if(py_matchexc(tp_KeyError)) { // Function& func = frame->_callable->as<Function>();
py_clearexc(NULL); // if(func.decl == __dynamic_func_decl) {
NameError(name); // assert(func._closure != nullptr);
} // bool ok = func._closure->del(_name);
goto __ERROR; // if(!ok) vm->NameError(_name);
// } else {
// vm->NameError(_name);
// }
} }
}else{ } else {
// globals bool ok = py_deldict(frame->module, name);
if(py_delitem(&frame->p0[0], TOP())) { if(!ok) {
POP(); NameError(name);
DISPATCH();
} else {
if(py_matchexc(tp_KeyError)) {
py_clearexc(NULL);
NameError(name);
}
goto __ERROR; goto __ERROR;
} }
} }
@ -954,9 +901,8 @@ FrameResult VM__run_top_frame(VM* self) {
case OP_WITH_ENTER: { case OP_WITH_ENTER: {
// [expr] // [expr]
py_push(TOP()); py_push(TOP());
if(!py_pushmethod(__enter__)) { if(!py_pushmethod(__enter__)){
TypeError("'%t' object does not support the context manager protocol", TypeError("'%t' object does not support the context manager protocol", TOP()->type);
TOP()->type);
goto __ERROR; goto __ERROR;
} }
if(!py_vectorcall(0, 0)) goto __ERROR; if(!py_vectorcall(0, 0)) goto __ERROR;
@ -966,9 +912,8 @@ FrameResult VM__run_top_frame(VM* self) {
case OP_WITH_EXIT: { case OP_WITH_EXIT: {
// [expr] // [expr]
py_push(TOP()); py_push(TOP());
if(!py_pushmethod(__exit__)) { if(!py_pushmethod(__exit__)){
TypeError("'%t' object does not support the context manager protocol", TypeError("'%t' object does not support the context manager protocol", TOP()->type);
TOP()->type);
goto __ERROR; goto __ERROR;
} }
if(!py_vectorcall(0, 0)) goto __ERROR; if(!py_vectorcall(0, 0)) goto __ERROR;

View File

@ -2,7 +2,6 @@
#include "pocketpy/objects/codeobject.h" #include "pocketpy/objects/codeobject.h"
#include "pocketpy/objects/object.h" #include "pocketpy/objects/object.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
#include <stdbool.h>
void ValueStack__ctor(ValueStack* self) { void ValueStack__ctor(ValueStack* self) {
self->sp = self->begin; self->sp = self->begin;
@ -38,20 +37,18 @@ void UnwindTarget__delete(UnwindTarget* self) { free(self); }
Frame* Frame__new(const CodeObject* co, Frame* Frame__new(const CodeObject* co,
py_GlobalRef module, py_GlobalRef module,
py_StackRef p0,
py_StackRef locals,
bool has_function, bool has_function,
bool is_dynamic) { py_StackRef p0,
py_StackRef locals) {
static_assert(sizeof(Frame) <= kPoolFrameBlockSize, "!(sizeof(Frame) <= kPoolFrameBlockSize)"); static_assert(sizeof(Frame) <= kPoolFrameBlockSize, "!(sizeof(Frame) <= kPoolFrameBlockSize)");
Frame* self = PoolFrame_alloc(); Frame* self = PoolFrame_alloc();
self->f_back = NULL; self->f_back = NULL;
self->ip = (Bytecode*)co->codes.data - 1; self->ip = (Bytecode*)co->codes.data - 1;
self->co = co; self->co = co;
self->module = module; self->module = module;
self->has_function = has_function;
self->p0 = p0; self->p0 = p0;
self->locals = locals; self->locals = locals;
self->has_function = has_function;
self->is_dynamic = is_dynamic;
self->uw_list = NULL; self->uw_list = NULL;
return self; return self;
} }
@ -153,6 +150,5 @@ int Frame__iblock(const Frame* self) {
} }
py_TValue* Frame__f_locals_try_get(Frame* self, py_Name name) { py_TValue* Frame__f_locals_try_get(Frame* self, py_Name name) {
assert(!self->is_dynamic);
return FastLocals__try_get_by_name(self->locals, self->co, name); return FastLocals__try_get_by_name(self->locals, self->co, name);
} }

View File

@ -7,7 +7,6 @@
#include "pocketpy/objects/base.h" #include "pocketpy/objects/base.h"
#include "pocketpy/common/_generated.h" #include "pocketpy/common/_generated.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
#include <stdbool.h>
static char* pk_default_import_file(const char* path) { static char* pk_default_import_file(const char* path) {
#if PK_ENABLE_OS #if PK_ENABLE_OS
@ -72,6 +71,7 @@ void VM__ctor(VM* self) {
self->is_stopiteration = false; self->is_stopiteration = false;
self->__curr_class = NULL; self->__curr_class = NULL;
self->__dynamic_func_decl = NULL;
ManagedHeap__ctor(&self->heap, self); ManagedHeap__ctor(&self->heap, self);
ValueStack__ctor(&self->stack); ValueStack__ctor(&self->stack);
@ -113,8 +113,7 @@ void VM__ctor(VM* self) {
validate(tp_BaseException, pk_BaseException__register()); validate(tp_BaseException, pk_BaseException__register());
validate(tp_Exception, pk_Exception__register()); validate(tp_Exception, pk_Exception__register());
validate(tp_bytes, pk_bytes__register()); validate(tp_bytes, pk_bytes__register());
validate(tp_namedict, pk_namedict__register()); validate(tp_mappingproxy, pk_newtype("mappingproxy", tp_object, NULL, NULL, false, true));
validate(tp_locals, pk_locals__register());
validate(tp_dict, pk_dict__register()); validate(tp_dict, pk_dict__register());
validate(tp_dict_items, pk_dict_items__register()); validate(tp_dict_items, pk_dict_items__register());
@ -213,6 +212,7 @@ void VM__ctor(VM* self) {
} }
void VM__dtor(VM* self) { void VM__dtor(VM* self) {
if(self->__dynamic_func_decl) { PK_DECREF(self->__dynamic_func_decl); }
// destroy all objects // destroy all objects
ManagedHeap__dtor(&self->heap); ManagedHeap__dtor(&self->heap);
// clear frames // clear frames
@ -429,10 +429,10 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
memcpy(argv, self->__vectorcall_buffer, co->nlocals * sizeof(py_TValue)); memcpy(argv, self->__vectorcall_buffer, co->nlocals * sizeof(py_TValue));
// submit the call // submit the call
if(!fn->cfunc) { if(!fn->cfunc) {
VM__push_frame(self, Frame__new(co, &fn->module, p0, argv, true, false)); VM__push_frame(self, Frame__new(co, &fn->module, true, p0, argv));
return opcall ? RES_CALL : VM__run_top_frame(self); return opcall ? RES_CALL : VM__run_top_frame(self);
} else { } else {
bool ok = py_callcfunc(fn->cfunc, co->nlocals, argv); bool ok = fn->cfunc(co->nlocals, argv);
self->stack.sp = p0; self->stack.sp = p0;
return ok ? RES_RETURN : RES_ERROR; return ok ? RES_RETURN : RES_ERROR;
} }
@ -453,16 +453,22 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
// initialize local variables to py_NIL // initialize local variables to py_NIL
memset(p1, 0, (char*)self->stack.sp - (char*)p1); memset(p1, 0, (char*)self->stack.sp - (char*)p1);
// submit the call // submit the call
VM__push_frame(self, Frame__new(co, &fn->module, p0, argv, true, false)); VM__push_frame(self, Frame__new(co, &fn->module, true, p0, argv));
return opcall ? RES_CALL : VM__run_top_frame(self); return opcall ? RES_CALL : VM__run_top_frame(self);
case FuncType_GENERATOR: { case FuncType_GENERATOR: {
bool ok = prepare_py_call(self->__vectorcall_buffer, argv, p1, kwargc, fn->decl); bool ok = prepare_py_call(self->__vectorcall_buffer, argv, p1, kwargc, fn->decl);
if(!ok) return RES_ERROR; if(!ok) return RES_ERROR;
Frame* frame = Frame__new(co, &fn->module, p0, argv, false, false); Frame* frame = Frame__new(co, &fn->module, false, p0, argv);
pk_newgenerator(py_retval(), frame, self->__vectorcall_buffer, co->nlocals); pk_newgenerator(py_retval(), frame, self->__vectorcall_buffer, co->nlocals);
self->stack.sp = p0; self->stack.sp = p0;
return RES_RETURN; return RES_RETURN;
} }
// prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
// s_data.reset(p0);
// callstack.emplace(nullptr, co, fn._module, callable.get(), nullptr);
// return __py_generator(
// callstack.popx(),
// ArgsView(__vectorcall_buffer, __vectorcall_buffer + co->nlocals));
default: c11__unreachedable(); default: c11__unreachedable();
}; };

View File

@ -7,7 +7,6 @@
#include "pocketpy/objects/object.h" #include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h" #include "pocketpy/interpreter/vm.h"
#include "pocketpy/compiler/compiler.h" #include "pocketpy/compiler/compiler.h"
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
VM* pk_current_vm; VM* pk_current_vm;
@ -78,14 +77,10 @@ const char* pk_opname(Opcode op) {
return OP_NAMES[op]; return OP_NAMES[op];
} }
static bool _py_exec(const char* source, bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) {
const char* filename,
enum py_CompileMode mode,
py_Ref module,
bool is_dynamic) {
VM* vm = pk_current_vm; VM* vm = pk_current_vm;
CodeObject co; CodeObject co;
SourceData_ src = SourceData__rcnew(source, filename, mode, is_dynamic); SourceData_ src = SourceData__rcnew(source, filename, mode, false);
Error* err = pk_compile(src, &co); Error* err = pk_compile(src, &co);
if(err) { if(err) {
py_exception(tp_SyntaxError, err->msg); py_exception(tp_SyntaxError, err->msg);
@ -98,13 +93,7 @@ static bool _py_exec(const char* source,
if(!module) module = &vm->main; if(!module) module = &vm->main;
py_StackRef sp = vm->stack.sp; Frame* frame = Frame__new(&co, module, false, vm->stack.sp, vm->stack.sp);
if(is_dynamic) {
// [globals, locals]
sp -= 2;
}
Frame* frame = Frame__new(&co, module, sp, sp, false, is_dynamic);
VM__push_frame(vm, frame); VM__push_frame(vm, frame);
FrameResult res = VM__run_top_frame(vm); FrameResult res = VM__run_top_frame(vm);
CodeObject__dtor(&co); CodeObject__dtor(&co);
@ -114,26 +103,15 @@ static bool _py_exec(const char* source,
c11__unreachedable(); c11__unreachedable();
} }
bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) {
return _py_exec(source, filename, mode, module, false);
}
bool py_execdyn(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) {
return _py_exec(source, filename, mode, module, true);
}
bool py_call(py_Ref f, int argc, py_Ref argv) { bool py_call(py_Ref f, int argc, py_Ref argv) {
if(f->type == tp_nativefunc) { if(f->type == tp_nativefunc) {
return py_callcfunc(f->_cfunc, argc, argv); return py_callcfunc(f->_cfunc, argc, argv);
} else { } else {
py_StackRef p0 = py_peek(0);
py_push(f); py_push(f);
py_pushnil(); py_pushnil();
for(int i = 0; i < argc; i++) for(int i = 0; i < argc; i++)
py_push(py_offset(argv, i)); py_push(py_offset(argv, i));
bool ok = py_vectorcall(argc, 0); return py_vectorcall(argc, 0);
pk_current_vm->stack.sp = p0;
return ok;
} }
} }
@ -142,16 +120,14 @@ bool py_callcfunc(py_CFunction f, int argc, py_Ref argv) {
py_newnil(py_retval()); py_newnil(py_retval());
bool ok = f(argc, argv); bool ok = f(argc, argv);
if(!ok) return false; if(!ok) return false;
if(py_peek(0) != p0) if(py_peek(0) != p0) c11__abort("py_CFunction corrupts the stack! Did you forget to call `py_pop()`?");
c11__abort("py_CFunction corrupts the stack! Did you forget to call `py_pop()`?"); if(py_isnil(py_retval())) c11__abort("py_CFunction returns nothing! Did you forget to call `py_newnone(py_retval())`?");
if(py_isnil(py_retval()))
c11__abort(
"py_CFunction returns nothing! Did you forget to call `py_newnone(py_retval())`?");
return true; return true;
} }
bool py_vectorcall(uint16_t argc, uint16_t kwargc) { bool py_vectorcall(uint16_t argc, uint16_t kwargc) {
return VM__vectorcall(pk_current_vm, argc, kwargc, false) != RES_ERROR; VM* vm = pk_current_vm;
return VM__vectorcall(vm, argc, kwargc, false) != RES_ERROR;
} }
py_Ref py_retval() { return &pk_current_vm->last_retval; } py_Ref py_retval() { return &pk_current_vm->last_retval; }

View File

@ -5,7 +5,6 @@
#include "pocketpy/common/sstream.h" #include "pocketpy/common/sstream.h"
#include "pocketpy/interpreter/vm.h" #include "pocketpy/interpreter/vm.h"
#include "pocketpy/common/_generated.h" #include "pocketpy/common/_generated.h"
#include <math.h>
py_Ref py_getmodule(const char* path) { py_Ref py_getmodule(const char* path) {
VM* vm = pk_current_vm; VM* vm = pk_current_vm;
@ -232,37 +231,6 @@ static bool builtins_divmod(int argc, py_Ref argv) {
return pk_callmagic(__divmod__, 2, argv); return pk_callmagic(__divmod__, 2, argv);
} }
static bool builtins_round(int argc, py_Ref argv) {
py_i64 ndigits;
if(argc == 1) {
ndigits = -1;
} else if(argc == 2) {
PY_CHECK_ARG_TYPE(1, tp_int);
ndigits = py_toint(py_arg(1));
if(ndigits < 0) return ValueError("ndigits should be non-negative");
} else {
return TypeError("round() takes 1 or 2 arguments");
}
if(py_isint(py_arg(0))) {
py_assign(py_retval(), py_arg(0));
return true;
}
PY_CHECK_ARG_TYPE(0, tp_float);
py_f64 x = py_tofloat(py_arg(0));
py_f64 offset = x >= 0 ? 0.5 : -0.5;
if(ndigits == -1) {
py_newint(py_retval(), (py_i64)(x + offset));
return true;
}
py_f64 factor = pow(10, ndigits);
py_newfloat(py_retval(), (py_i64)(x * factor + offset) / factor);
return true;
}
static bool builtins_print(int argc, py_Ref argv) { static bool builtins_print(int argc, py_Ref argv) {
int length; int length;
py_TValue* args = pk_arrayview(argv, &length); py_TValue* args = pk_arrayview(argv, &length);
@ -284,6 +252,20 @@ static bool builtins_print(int argc, py_Ref argv) {
return true; return true;
} }
static bool builtins_exec(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
Frame* frame = pk_current_vm->top_frame;
return py_exec(py_tostr(argv), "<exec>", EXEC_MODE, frame->module);
}
static bool builtins_eval(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
Frame* frame = pk_current_vm->top_frame;
return py_exec(py_tostr(argv), "<eval>", EVAL_MODE, frame->module);
}
static bool builtins_isinstance(int argc, py_Ref argv) { static bool builtins_isinstance(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
if(py_istuple(py_arg(1))) { if(py_istuple(py_arg(1))) {
@ -319,9 +301,10 @@ static bool builtins_getattr(int argc, py_Ref argv) {
if(argc == 2) { if(argc == 2) {
return py_getattr(py_arg(0), name); return py_getattr(py_arg(0), name);
} else if(argc == 3) { } else if(argc == 3) {
py_StackRef p0 = py_peek(0);
bool ok = py_getattr(py_arg(0), name); bool ok = py_getattr(py_arg(0), name);
if(!ok && py_matchexc(tp_AttributeError)) { if(!ok && py_matchexc(tp_AttributeError)) {
py_clearexc(NULL); py_clearexc(p0);
py_assign(py_retval(), py_arg(2)); py_assign(py_retval(), py_arg(2));
return true; // default value return true; // default value
} }
@ -344,13 +327,14 @@ static bool builtins_hasattr(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str); PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1))); py_Name name = py_namev(py_tosv(py_arg(1)));
py_StackRef p0 = py_peek(0);
bool ok = py_getattr(py_arg(0), name); bool ok = py_getattr(py_arg(0), name);
if(ok) { if(ok) {
py_newbool(py_retval(), true); py_newbool(py_retval(), true);
return true; return true;
} }
if(py_matchexc(tp_AttributeError)) { if(py_matchexc(tp_AttributeError)) {
py_clearexc(NULL); py_clearexc(p0);
py_newbool(py_retval(), false); py_newbool(py_retval(), false);
return true; return true;
} }
@ -385,64 +369,6 @@ static bool builtins_ord(int argc, py_Ref argv) {
return true; return true;
} }
static bool builtins_globals(int argc, py_Ref argv) {
Frame* frame = pk_current_vm->top_frame;
if(frame->is_dynamic) {
py_assign(py_retval(), &frame->p0[0]);
return true;
}
pk_mappingproxy__namedict(py_retval(), frame->module);
return true;
}
static bool builtins_locals(int argc, py_Ref argv) {
Frame* frame = pk_current_vm->top_frame;
if(frame->is_dynamic) {
py_assign(py_retval(), &frame->p0[1]);
return true;
}
if(!frame->has_function) return builtins_globals(argc, argv);
pk_mappingproxy__locals(py_retval(), frame);
return true;
}
static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_CompileMode mode) {
PY_CHECK_ARG_TYPE(0, tp_str);
Frame* frame = pk_current_vm->top_frame;
switch(argc) {
case 1: {
// system globals + system locals
if(!builtins_globals(0, NULL)) return false;
py_push(py_retval());
if(!builtins_locals(0, NULL)) return false;
py_push(py_retval());
break;
}
case 2: {
// user globals + user globals
py_push(py_arg(1));
py_push(py_arg(1));
break;
}
case 3: {
// user globals + user locals
py_push(py_arg(1));
py_push(py_arg(2));
break;
}
default: return TypeError("%s() takes at most 3 arguments", title);
}
return py_execdyn(py_tostr(argv), "<string>", mode, frame->module);
}
static bool builtins_exec(int argc, py_Ref argv) {
return _builtins_execdyn("exec", argc, argv, EXEC_MODE);
}
static bool builtins_eval(int argc, py_Ref argv) {
return _builtins_execdyn("eval", argc, argv, EVAL_MODE);
}
static bool NoneType__repr__(int argc, py_Ref argv) { static bool NoneType__repr__(int argc, py_Ref argv) {
py_newstr(py_retval(), "None"); py_newstr(py_retval(), "None");
return true; return true;
@ -469,7 +395,9 @@ py_TValue pk_builtins__register() {
py_bindfunc(builtins, "hash", builtins_hash); py_bindfunc(builtins, "hash", builtins_hash);
py_bindfunc(builtins, "abs", builtins_abs); py_bindfunc(builtins, "abs", builtins_abs);
py_bindfunc(builtins, "divmod", builtins_divmod); py_bindfunc(builtins, "divmod", builtins_divmod);
py_bindfunc(builtins, "round", builtins_round);
py_bindfunc(builtins, "exec", builtins_exec);
py_bindfunc(builtins, "eval", builtins_eval);
py_bind(builtins, "print(*args, sep=' ', end='\\n')", builtins_print); py_bind(builtins, "print(*args, sep=' ', end='\\n')", builtins_print);
@ -484,11 +412,6 @@ py_TValue pk_builtins__register() {
py_bindfunc(builtins, "chr", builtins_chr); py_bindfunc(builtins, "chr", builtins_chr);
py_bindfunc(builtins, "ord", builtins_ord); py_bindfunc(builtins, "ord", builtins_ord);
py_bindfunc(builtins, "globals", builtins_globals);
py_bindfunc(builtins, "locals", builtins_locals);
py_bindfunc(builtins, "exec", builtins_exec);
py_bindfunc(builtins, "eval", builtins_eval);
// some patches // some patches
py_bindmagic(tp_NoneType, __repr__, NoneType__repr__); py_bindmagic(tp_NoneType, __repr__, NoneType__repr__);
py_bindmagic(tp_ellipsis, __repr__, ellipsis__repr__); py_bindmagic(tp_ellipsis, __repr__, ellipsis__repr__);

View File

@ -1,123 +0,0 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
#include "pocketpy/common/sstream.h"
void pk_mappingproxy__namedict(py_Ref out, py_Ref object){
py_newobject(py_retval(), tp_namedict, 1, 0);
assert(object->is_ptr && object->_obj->slots == -1);
py_setslot(py_retval(), 0, object);
}
static bool namedict__getitem__(int argc, py_Ref argv){
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1)));
py_Ref res = py_getdict(py_getslot(argv, 0), name);
if(!res) return KeyError(py_arg(1));
py_assign(py_retval(), res);
return true;
}
static bool namedict__setitem__(int argc, py_Ref argv){
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1)));
py_setdict(py_getslot(argv, 0), name, py_arg(2));
py_newnone(py_retval());
return true;
}
static bool namedict__delitem__(int argc, py_Ref argv){
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1)));
if(!py_deldict(py_getslot(argv, 0), name)) return KeyError(py_arg(1));
py_newnone(py_retval());
return true;
}
static bool namedict__contains__(int argc, py_Ref argv){
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1)));
py_Ref res = py_getdict(py_getslot(argv, 0), name);
py_newbool(py_retval(), res != NULL);
return true;
}
py_Type pk_namedict__register() {
py_Type type = pk_newtype("namedict", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __getitem__, namedict__getitem__);
py_bindmagic(type, __setitem__, namedict__setitem__);
py_bindmagic(type, __delitem__, namedict__delitem__);
py_bindmagic(type, __contains__, namedict__contains__);
return type;
}
//////////////////////
void pk_mappingproxy__locals(py_Ref out, Frame* frame){
assert(frame->has_function && !frame->is_dynamic);
Frame** ud = py_newobject(py_retval(), tp_locals, 0, sizeof(Frame*));
*ud = frame;
}
static bool locals__getitem__(int argc, py_Ref argv){
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str);
Frame** ud = py_touserdata(argv);
py_Name name = py_namev(py_tosv(py_arg(1)));
py_Ref slot = Frame__f_locals_try_get(*ud, name);
if(!slot || py_isnil(slot)) return KeyError(py_arg(1));
py_assign(py_retval(), slot);
return true;
}
static bool locals__setitem__(int argc, py_Ref argv){
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_str);
Frame** ud = py_touserdata(argv);
py_Name name = py_namev(py_tosv(py_arg(1)));
py_Ref slot = Frame__f_locals_try_get(*ud, name);
if(!slot) return KeyError(py_arg(1));
py_assign(slot, py_arg(2));
py_newnone(py_retval());
return true;
}
static bool locals__delitem__(int argc, py_Ref argv){
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str);
Frame** ud = py_touserdata(argv);
py_Name name = py_namev(py_tosv(py_arg(1)));
py_Ref res = Frame__f_locals_try_get(*ud, name);
if(!res || py_isnil(res)) return KeyError(py_arg(1));
py_newnil(res);
py_newnone(py_retval());
return true;
}
static bool locals__contains__(int argc, py_Ref argv){
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str);
Frame** ud = py_touserdata(argv);
py_Name name = py_namev(py_tosv(py_arg(1)));
py_Ref slot = Frame__f_locals_try_get(*ud, name);
py_newbool(py_retval(), slot && !py_isnil(slot));
return true;
}
py_Type pk_locals__register() {
py_Type type = pk_newtype("locals", tp_locals, NULL, NULL, false, true);
py_bindmagic(type, __getitem__, locals__getitem__);
py_bindmagic(type, __setitem__, locals__setitem__);
py_bindmagic(type, __delitem__, locals__delitem__);
py_bindmagic(type, __contains__, locals__contains__);
return type;
}

View File

@ -44,16 +44,6 @@ static bool object__repr__(int argc, py_Ref argv) {
return true; return true;
} }
static bool object__dict__getter(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
if(argv->is_ptr && argv->_obj->slots == -1){
pk_mappingproxy__namedict(py_retval(), argv);
}else{
py_newnone(py_retval());
}
return true;
}
static bool type__repr__(int argc, py_Ref argv) { static bool type__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
c11_sbuf buf; c11_sbuf buf;
@ -98,7 +88,6 @@ void pk_object__register() {
py_bindmagic(tp_object, __eq__, object__eq__); py_bindmagic(tp_object, __eq__, object__eq__);
py_bindmagic(tp_object, __ne__, object__ne__); py_bindmagic(tp_object, __ne__, object__ne__);
py_bindmagic(tp_object, __repr__, object__repr__); py_bindmagic(tp_object, __repr__, object__repr__);
py_bindproperty(tp_object, "__dict__", object__dict__getter, NULL);
py_bindmagic(tp_type, __repr__, type__repr__); py_bindmagic(tp_type, __repr__, type__repr__);
py_bindmagic(tp_type, __new__, type__new__); py_bindmagic(tp_type, __new__, type__new__);

View File

@ -75,9 +75,10 @@ int py_next(py_Ref val) {
TypeError("'%t' object is not an iterator", val->type); TypeError("'%t' object is not an iterator", val->type);
return -1; return -1;
} }
py_StackRef p0 = py_peek(0);
if(py_call(tmp, 1, val)) return true; if(py_call(tmp, 1, val)) return true;
if(vm->curr_exception.type == tp_StopIteration) { if(vm->curr_exception.type == tp_StopIteration) {
py_clearexc(NULL); py_clearexc(p0);
vm->is_stopiteration = true; vm->is_stopiteration = true;
} }
int retval = vm->is_stopiteration ? 0 : -1; int retval = vm->is_stopiteration ? 0 : -1;

View File

@ -327,8 +327,8 @@ assert s.step == 3
# test slice.__repr__ # test slice.__repr__
assert type(repr(slice(1,1,1))) is str assert type(repr(slice(1,1,1))) is str
# /************ namedict ************/ # /************ mappingproxy ************/
# test namedict.keys: # test mappingproxy.keys:
class A(): class A():
def __init__(self): def __init__(self):
self.a = 10 self.a = 10
@ -336,12 +336,12 @@ class A():
pass pass
my_namedict = A().__dict__ my_mappingproxy = A().__dict__
assert type(my_namedict.keys()) is list assert type(my_mappingproxy.keys()) is list
# 未完全测试准确性----------------------------------------------- # 未完全测试准确性-----------------------------------------------
# test namedict.values: # test mappingproxy.values:
class A(): class A():
def __init__(self): def __init__(self):
self.a = 10 self.a = 10
@ -349,8 +349,8 @@ class A():
pass pass
my_namedict = A().__dict__ my_mappingproxy = A().__dict__
assert type(my_namedict.values()) is list assert type(my_mappingproxy.values()) is list
class A(): class A():
@ -360,8 +360,8 @@ class A():
pass pass
my_namedict = A().__dict__ my_mappingproxy = A().__dict__
assert type(len(my_namedict)) is int assert type(len(my_mappingproxy)) is int
class A(): class A():
@ -371,11 +371,11 @@ class A():
pass pass
my_namedict = A().__dict__ my_mappingproxy = A().__dict__
try: try:
hash(my_namedict) hash(my_mappingproxy)
print('未能拦截错误, 在测试 namedict.__hash__') print('未能拦截错误, 在测试 mappingproxy.__hash__')
exit(1) exit(1)
except TypeError: except TypeError:
pass pass
@ -393,7 +393,7 @@ except TypeError:
pass pass
# 未完全测试准确性----------------------------------------------- # 未完全测试准确性-----------------------------------------------
# test namedict.__repr__: # test mappingproxy.__repr__:
class A(): class A():
def __init__(self): def __init__(self):
self.a = 10 self.a = 10
@ -401,8 +401,8 @@ class A():
pass pass
my_namedict = A().__dict__ my_mappingproxy = A().__dict__
assert type(repr(my_namedict)) is str assert type(repr(my_mappingproxy)) is str
# /************ dict ************/ # /************ dict ************/