This commit is contained in:
blueloveTH 2023-04-18 00:03:29 +08:00
parent 1972234f22
commit c89a74db1e
10 changed files with 90 additions and 48 deletions

View File

@ -399,18 +399,14 @@ __NEXT_STEP:;
list.push_back(obj);
} DISPATCH();
TARGET(DICT_ADD) {
PyObject* kv = POPX();
Tuple& t = CAST(Tuple&, kv);
PyObject* self;
PyObject* callable = get_unbound_method(SECOND(), __setitem__, &self);
call_method(self, callable, t[0], t[1]);
} DISPATCH();
TARGET(SET_ADD) {
PyObject* val = POPX();
PyObject* self;
PyObject* callable = get_unbound_method(SECOND(), m_add, &self);
call_method(self, callable, val);
_0 = POPX();
Tuple& t = CAST(Tuple&, _0);
call_method(SECOND(), __setitem__, t[0], t[1]);
} DISPATCH();
TARGET(SET_ADD)
_0 = POPX();
call_method(SECOND(), m_add, _0);
DISPATCH();
/*****************************************/
TARGET(UNARY_NEGATIVE)
TOP() = num_negated(TOP());
@ -421,12 +417,17 @@ __NEXT_STEP:;
/*****************************************/
TARGET(GET_ITER)
TOP() = asIter(TOP());
check_type(TOP(), tp_iterator);
DISPATCH();
TARGET(FOR_ITER) {
#if DEBUG_EXTRA_CHECK
BaseIter* it = PyIter_AS_C(TOP());
_0 = it->next();
if(_0 != nullptr){
PUSH(_0);
#else
BaseIter* it = _PyIter_AS_C(TOP());
#endif
PyObject* obj = it->next();
if(obj != nullptr){
PUSH(obj);
}else{
int target = co_blocks[byte.block].end;
frame->jump_abs_break(target);

View File

@ -81,7 +81,7 @@ struct VoidP{
static void _register(VM* vm, PyObject* mod, PyObject* type){
vm->bind_static_method<1>(type, "__new__", CPP_NOT_IMPLEMENTED());
vm->bind_static_method<1>(type, "__repr__", [](VM* vm, const Args& args){
vm->bind_static_method<1>(type, "__repr__", [](VM* vm, ArgsView args){
VoidP& self = CAST(VoidP&, args[0]);
std::stringstream ss;
ss << "<void* at " << self.ptr << ">";

View File

@ -35,7 +35,7 @@
#define DEBUG_NO_BUILTIN_MODULES 0
#define DEBUG_EXTRA_CHECK 1
#define DEBUG_DIS_EXEC 0
#define DEBUG_CEVAL_STEP 1
#define DEBUG_CEVAL_STEP 0
#define DEBUG_CEVAL_STEP_MIN 0
#define DEBUG_FULL_EXCEPTION 0
#define DEBUG_MEMORY_POOL 0

View File

@ -154,7 +154,12 @@ struct ValueStack {
bool empty() const { return _sp == _begin; }
PyObject** begin() { return _begin; }
PyObject** end() { return _sp; }
void reset(PyObject** sp) { _sp = sp; }
void reset(PyObject** sp) {
#if DEBUG_EXTRA_CHECK
if(sp < _begin || sp > _begin + MAX_SIZE) FATAL_ERROR();
#endif
_sp = sp;
}
void clear() { _sp = _begin; }
bool is_overflow() const { return _sp >= _begin + MAX_SIZE; }

View File

@ -27,14 +27,17 @@ public:
template <typename T>
class ArrayIter final: public BaseIter {
PyObject* ref;
T* array;
int index;
public:
ArrayIter(VM* vm, PyObject* ref) : BaseIter(vm), ref(ref), index(0) {}
ArrayIter(VM* vm, PyObject* ref) : BaseIter(vm), ref(ref) {
array = &OBJ_GET(T, ref);
index = 0;
}
PyObject* next() override{
const T* p = &OBJ_GET(T, ref);
if(index == p->size()) return nullptr;
return p->operator[](index++);
if(index >= array->size()) return nullptr;
return array->operator[](index++);
}
void _gc_mark() const override {
@ -66,15 +69,15 @@ inline PyObject* Generator::next(){
// reset frame._sp_base
frame._sp_base = frame._s->_sp;
// restore the context
for(PyObject* obj: s_data) frame._s->push(obj);
s_data.clear();
for(PyObject* obj: s_backup) frame._s->push(obj);
s_backup.clear();
vm->callstack.push(std::move(frame));
PyObject* ret = vm->_run_top_frame();
if(ret == vm->_py_op_yield){
// backup the context
frame = std::move(vm->callstack.top());
PyObject* ret = frame._s->popx();
for(PyObject* obj: frame.stack_view()) s_data.push_back(obj);
for(PyObject* obj: frame.stack_view()) s_backup.push_back(obj);
vm->_pop_frame();
state = 1;
return ret;
@ -86,6 +89,7 @@ inline PyObject* Generator::next(){
inline void Generator::_gc_mark() const{
frame._gc_mark();
for(PyObject* obj: s_backup) OBJ_MARK(obj);
}
template<typename T>

View File

@ -118,9 +118,7 @@ inline void init_builtins(VM* _vm) {
_vm->bind_builtin_func<1>("repr", CPP_LAMBDA(vm->asRepr(args[0])));
_vm->bind_builtin_func<1>("len", [](VM* vm, ArgsView args){
PyObject* self;
PyObject* len_f = vm->get_unbound_method(args[0], __len__, &self);
return vm->call_method(self, len_f);
return vm->call_method(args[0], __len__);
});
_vm->bind_builtin_func<1>("hash", [](VM* vm, ArgsView args){
@ -524,7 +522,7 @@ inline void init_builtins(VM* _vm) {
});
_vm->bind_method<0>("tuple", "__iter__", [](VM* vm, ArgsView args) {
return vm->PyIter(ArrayIter<Args>(vm, args[0]));
return vm->PyIter(ArrayIter<Tuple>(vm, args[0]));
});
_vm->bind_method<1>("tuple", "__getitem__", [](VM* vm, ArgsView args) {
@ -958,7 +956,7 @@ extern "C" {
for(int i=0; name[i]; i++) if(name[i] == ' ') return nullptr;
std::string f_header = std::string(mod) + '.' + name + '#' + std::to_string(kGlobalBindId++);
pkpy::PyObject* obj = vm->_modules.contains(mod) ? vm->_modules[mod] : vm->new_module(mod);
vm->bind_func<-1>(obj, name, [ret_code, f_header](pkpy::VM* vm, const pkpy::Args& args){
vm->bind_func<-1>(obj, name, [ret_code, f_header](pkpy::VM* vm, pkpy::ArgsView args){
std::stringstream ss;
ss << f_header;
for(int i=0; i<args.size(); i++){

View File

@ -45,7 +45,8 @@ protected:
VM* vm;
public:
REPL(VM* vm) : vm(vm){
(*vm->_stdout) << ("pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ")\n");
(*vm->_stdout) << ("pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ") ");
(*vm->_stdout) << "[" << std::to_string(sizeof(void*) * 8) << " bit]" "\n";
(*vm->_stdout) << ("https://github.com/blueloveTH/pocketpy" "\n");
(*vm->_stdout) << ("Type \"exit()\" to exit." "\n");
}

View File

@ -93,7 +93,4 @@ struct ArgsView{
return ret;
}
};
using Args = ArgsView;
} // namespace pkpy

View File

@ -49,7 +49,7 @@ Str _read_file_cwd(const Str& name, bool* ok);
class Generator final: public BaseIter {
Frame frame;
int state; // 0,1,2
List s_data; // backup
List s_backup;
public:
Generator(VM* vm, Frame&& frame): BaseIter(vm), frame(std::move(frame)), state(0) {}
@ -311,6 +311,11 @@ public:
check_type(obj, tp_iterator);
return static_cast<BaseIter*>(obj->value());
}
BaseIter* _PyIter_AS_C(PyObject* obj)
{
return static_cast<BaseIter*>(obj->value());
}
/***** Error Reporter *****/
void _error(StrName name, const Str& msg){
@ -658,19 +663,18 @@ inline void VM::_log_s_data(const char* title) {
if(callstack.empty()) return;
std::stringstream ss;
if(title) ss << title << " | ";
std::vector<PyObject**> sp_bases;
std::map<PyObject**, int> sp_bases;
for(Frame& f: callstack.data()){
sp_bases.push_back(f._sp_base);
if(f._sp_base == nullptr) FATAL_ERROR();
sp_bases[f._sp_base] += 1;
}
std::reverse(sp_bases.begin(), sp_bases.end());
FrameId frame = top_frame();
int line = frame->co->lines[frame->_ip];
ss << frame->co->name << ":" << line << " [";
for(PyObject*& obj: s_data){
if(&obj == sp_bases.back()){
ss << "| ";
sp_bases.pop_back();
}
for(PyObject** p=s_data.begin(); p!=s_data.end(); p++){
ss << std::string(sp_bases[p], '|');
if(sp_bases[p] > 0) ss << " ";
PyObject* obj = *p;
if(obj == nullptr) ss << "(nil)";
else if(obj == _py_begin_call) ss << "BEGIN_CALL";
else if(obj == _py_null) ss << "NULL";
@ -680,8 +684,19 @@ inline void VM::_log_s_data(const char* title) {
else if(obj == None) ss << "None";
else if(obj == True) ss << "True";
else if(obj == False) ss << "False";
// else ss << obj << "(" << obj_type_name(this, obj->type) << ")";
else ss << "(" << obj_type_name(this, obj->type) << ")";
else if(is_type(obj, tp_function)){
auto& f = CAST(Function&, obj);
ss << f.decl->code->name << "(...)";
} else if(is_type(obj, tp_type)){
Type t = OBJ_GET(Type, obj);
ss << "<class " + _all_types[t].name.escape() + ">";
} else if(is_type(obj, tp_list)){
auto& t = CAST(List&, obj);
ss << "list(size=" << t.size() << ")";
} else if(is_type(obj, tp_tuple)){
auto& t = CAST(Tuple&, obj);
ss << "tuple(size=" << t.size() << ")";
} else ss << "(" << obj_type_name(this, obj->type) << ")";
ss << ", ";
}
std::string output = ss.str();
@ -891,12 +906,15 @@ inline PyObject* VM::_py_call(PyObject** sp_base, PyObject* callable, ArgsView a
if(!ok) TypeError(fmt(key.escape(), " is an invalid keyword argument for ", co->name, "()"));
}
PyObject* _module = fn._module != nullptr ? fn._module : top_frame()->_module;
// TODO: callable may be garbage collected
s_data.reset(sp_base);
PyObject** curr_sp = s_data._sp;
if(co->is_generator){
PyObject* ret = PyIter(Generator(this, Frame(&s_data, sp_base, co, _module, std::move(locals), fn._closure)));
s_data.reset(sp_base);
PyObject* ret = PyIter(Generator(this, Frame(&s_data, curr_sp, co, _module, std::move(locals), fn._closure)));
return ret;
}
callstack.emplace(&s_data, sp_base, co, _module, std::move(locals), fn._closure);
callstack.emplace(&s_data, curr_sp, co, _module, std::move(locals), fn._closure);
return nullptr;
}

View File

@ -1,6 +1,5 @@
## Function Tests.
def f1():
return 'f1'
assert f1() == 'f1'
@ -11,6 +10,11 @@ def f3(a,b):
return a - b
assert f3(1,2) == -1
def f4(a,b):
return a + f3(a, b)
assert f4(1,2) == 0
def fact(n):
if n == 1:
return 1
@ -27,9 +31,23 @@ assert f(b=5) == 6
assert f(a=5) == 4
assert f(b=5, a=5) == 10
def f(*args):
return 10 * sum(args)
assert f(1, 2, 3) == 60
def f(x, *args, y=3):
i = 0
for j in args:
i += j
return i * y
assert f(10, 1, 2, 3) == 18
def f(a, b, *c, d=2, e=5):
return a + b + d + e + sum(c)
assert f(1, 2, 3, 4) == 17
assert f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) == 62
assert f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, d=1, e=2) == 58
assert f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, e=1, d=2) == 58