mirror of
https://github.com/pocketpy/pocketpy
synced 2025-12-07 02:30:17 +00:00
...
This commit is contained in:
parent
1972234f22
commit
c89a74db1e
29
src/ceval.h
29
src/ceval.h
@ -399,18 +399,14 @@ __NEXT_STEP:;
|
|||||||
list.push_back(obj);
|
list.push_back(obj);
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(DICT_ADD) {
|
TARGET(DICT_ADD) {
|
||||||
PyObject* kv = POPX();
|
_0 = POPX();
|
||||||
Tuple& t = CAST(Tuple&, kv);
|
Tuple& t = CAST(Tuple&, _0);
|
||||||
PyObject* self;
|
call_method(SECOND(), __setitem__, t[0], t[1]);
|
||||||
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);
|
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
|
TARGET(SET_ADD)
|
||||||
|
_0 = POPX();
|
||||||
|
call_method(SECOND(), m_add, _0);
|
||||||
|
DISPATCH();
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
TARGET(UNARY_NEGATIVE)
|
TARGET(UNARY_NEGATIVE)
|
||||||
TOP() = num_negated(TOP());
|
TOP() = num_negated(TOP());
|
||||||
@ -421,12 +417,17 @@ __NEXT_STEP:;
|
|||||||
/*****************************************/
|
/*****************************************/
|
||||||
TARGET(GET_ITER)
|
TARGET(GET_ITER)
|
||||||
TOP() = asIter(TOP());
|
TOP() = asIter(TOP());
|
||||||
|
check_type(TOP(), tp_iterator);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
TARGET(FOR_ITER) {
|
TARGET(FOR_ITER) {
|
||||||
|
#if DEBUG_EXTRA_CHECK
|
||||||
BaseIter* it = PyIter_AS_C(TOP());
|
BaseIter* it = PyIter_AS_C(TOP());
|
||||||
_0 = it->next();
|
#else
|
||||||
if(_0 != nullptr){
|
BaseIter* it = _PyIter_AS_C(TOP());
|
||||||
PUSH(_0);
|
#endif
|
||||||
|
PyObject* obj = it->next();
|
||||||
|
if(obj != nullptr){
|
||||||
|
PUSH(obj);
|
||||||
}else{
|
}else{
|
||||||
int target = co_blocks[byte.block].end;
|
int target = co_blocks[byte.block].end;
|
||||||
frame->jump_abs_break(target);
|
frame->jump_abs_break(target);
|
||||||
|
|||||||
@ -81,7 +81,7 @@ struct VoidP{
|
|||||||
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
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, "__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]);
|
VoidP& self = CAST(VoidP&, args[0]);
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "<void* at " << self.ptr << ">";
|
ss << "<void* at " << self.ptr << ">";
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
#define DEBUG_NO_BUILTIN_MODULES 0
|
#define DEBUG_NO_BUILTIN_MODULES 0
|
||||||
#define DEBUG_EXTRA_CHECK 1
|
#define DEBUG_EXTRA_CHECK 1
|
||||||
#define DEBUG_DIS_EXEC 0
|
#define DEBUG_DIS_EXEC 0
|
||||||
#define DEBUG_CEVAL_STEP 1
|
#define DEBUG_CEVAL_STEP 0
|
||||||
#define DEBUG_CEVAL_STEP_MIN 0
|
#define DEBUG_CEVAL_STEP_MIN 0
|
||||||
#define DEBUG_FULL_EXCEPTION 0
|
#define DEBUG_FULL_EXCEPTION 0
|
||||||
#define DEBUG_MEMORY_POOL 0
|
#define DEBUG_MEMORY_POOL 0
|
||||||
|
|||||||
@ -154,7 +154,12 @@ struct ValueStack {
|
|||||||
bool empty() const { return _sp == _begin; }
|
bool empty() const { return _sp == _begin; }
|
||||||
PyObject** begin() { return _begin; }
|
PyObject** begin() { return _begin; }
|
||||||
PyObject** end() { return _sp; }
|
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; }
|
void clear() { _sp = _begin; }
|
||||||
bool is_overflow() const { return _sp >= _begin + MAX_SIZE; }
|
bool is_overflow() const { return _sp >= _begin + MAX_SIZE; }
|
||||||
|
|
||||||
|
|||||||
18
src/iter.h
18
src/iter.h
@ -27,14 +27,17 @@ public:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class ArrayIter final: public BaseIter {
|
class ArrayIter final: public BaseIter {
|
||||||
PyObject* ref;
|
PyObject* ref;
|
||||||
|
T* array;
|
||||||
int index;
|
int index;
|
||||||
public:
|
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{
|
PyObject* next() override{
|
||||||
const T* p = &OBJ_GET(T, ref);
|
if(index >= array->size()) return nullptr;
|
||||||
if(index == p->size()) return nullptr;
|
return array->operator[](index++);
|
||||||
return p->operator[](index++);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _gc_mark() const override {
|
void _gc_mark() const override {
|
||||||
@ -66,15 +69,15 @@ inline PyObject* Generator::next(){
|
|||||||
// reset frame._sp_base
|
// reset frame._sp_base
|
||||||
frame._sp_base = frame._s->_sp;
|
frame._sp_base = frame._s->_sp;
|
||||||
// restore the context
|
// restore the context
|
||||||
for(PyObject* obj: s_data) frame._s->push(obj);
|
for(PyObject* obj: s_backup) frame._s->push(obj);
|
||||||
s_data.clear();
|
s_backup.clear();
|
||||||
vm->callstack.push(std::move(frame));
|
vm->callstack.push(std::move(frame));
|
||||||
PyObject* ret = vm->_run_top_frame();
|
PyObject* ret = vm->_run_top_frame();
|
||||||
if(ret == vm->_py_op_yield){
|
if(ret == vm->_py_op_yield){
|
||||||
// backup the context
|
// backup the context
|
||||||
frame = std::move(vm->callstack.top());
|
frame = std::move(vm->callstack.top());
|
||||||
PyObject* ret = frame._s->popx();
|
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();
|
vm->_pop_frame();
|
||||||
state = 1;
|
state = 1;
|
||||||
return ret;
|
return ret;
|
||||||
@ -86,6 +89,7 @@ inline PyObject* Generator::next(){
|
|||||||
|
|
||||||
inline void Generator::_gc_mark() const{
|
inline void Generator::_gc_mark() const{
|
||||||
frame._gc_mark();
|
frame._gc_mark();
|
||||||
|
for(PyObject* obj: s_backup) OBJ_MARK(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|||||||
@ -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>("repr", CPP_LAMBDA(vm->asRepr(args[0])));
|
||||||
_vm->bind_builtin_func<1>("len", [](VM* vm, ArgsView args){
|
_vm->bind_builtin_func<1>("len", [](VM* vm, ArgsView args){
|
||||||
PyObject* self;
|
return vm->call_method(args[0], __len__);
|
||||||
PyObject* len_f = vm->get_unbound_method(args[0], __len__, &self);
|
|
||||||
return vm->call_method(self, len_f);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_builtin_func<1>("hash", [](VM* vm, ArgsView args){
|
_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) {
|
_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) {
|
_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;
|
for(int i=0; name[i]; i++) if(name[i] == ' ') return nullptr;
|
||||||
std::string f_header = std::string(mod) + '.' + name + '#' + std::to_string(kGlobalBindId++);
|
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);
|
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;
|
std::stringstream ss;
|
||||||
ss << f_header;
|
ss << f_header;
|
||||||
for(int i=0; i<args.size(); i++){
|
for(int i=0; i<args.size(); i++){
|
||||||
|
|||||||
@ -45,7 +45,8 @@ protected:
|
|||||||
VM* vm;
|
VM* vm;
|
||||||
public:
|
public:
|
||||||
REPL(VM* vm) : vm(vm){
|
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) << ("https://github.com/blueloveTH/pocketpy" "\n");
|
||||||
(*vm->_stdout) << ("Type \"exit()\" to exit." "\n");
|
(*vm->_stdout) << ("Type \"exit()\" to exit." "\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,7 +93,4 @@ struct ArgsView{
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using Args = ArgsView;
|
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
||||||
46
src/vm.h
46
src/vm.h
@ -49,7 +49,7 @@ Str _read_file_cwd(const Str& name, bool* ok);
|
|||||||
class Generator final: public BaseIter {
|
class Generator final: public BaseIter {
|
||||||
Frame frame;
|
Frame frame;
|
||||||
int state; // 0,1,2
|
int state; // 0,1,2
|
||||||
List s_data; // backup
|
List s_backup;
|
||||||
public:
|
public:
|
||||||
Generator(VM* vm, Frame&& frame): BaseIter(vm), frame(std::move(frame)), state(0) {}
|
Generator(VM* vm, Frame&& frame): BaseIter(vm), frame(std::move(frame)), state(0) {}
|
||||||
|
|
||||||
@ -312,6 +312,11 @@ public:
|
|||||||
return static_cast<BaseIter*>(obj->value());
|
return static_cast<BaseIter*>(obj->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BaseIter* _PyIter_AS_C(PyObject* obj)
|
||||||
|
{
|
||||||
|
return static_cast<BaseIter*>(obj->value());
|
||||||
|
}
|
||||||
|
|
||||||
/***** Error Reporter *****/
|
/***** Error Reporter *****/
|
||||||
void _error(StrName name, const Str& msg){
|
void _error(StrName name, const Str& msg){
|
||||||
_error(Exception(name, msg));
|
_error(Exception(name, msg));
|
||||||
@ -658,19 +663,18 @@ inline void VM::_log_s_data(const char* title) {
|
|||||||
if(callstack.empty()) return;
|
if(callstack.empty()) return;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
if(title) ss << title << " | ";
|
if(title) ss << title << " | ";
|
||||||
std::vector<PyObject**> sp_bases;
|
std::map<PyObject**, int> sp_bases;
|
||||||
for(Frame& f: callstack.data()){
|
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();
|
FrameId frame = top_frame();
|
||||||
int line = frame->co->lines[frame->_ip];
|
int line = frame->co->lines[frame->_ip];
|
||||||
ss << frame->co->name << ":" << line << " [";
|
ss << frame->co->name << ":" << line << " [";
|
||||||
for(PyObject*& obj: s_data){
|
for(PyObject** p=s_data.begin(); p!=s_data.end(); p++){
|
||||||
if(&obj == sp_bases.back()){
|
ss << std::string(sp_bases[p], '|');
|
||||||
ss << "| ";
|
if(sp_bases[p] > 0) ss << " ";
|
||||||
sp_bases.pop_back();
|
PyObject* obj = *p;
|
||||||
}
|
|
||||||
if(obj == nullptr) ss << "(nil)";
|
if(obj == nullptr) ss << "(nil)";
|
||||||
else if(obj == _py_begin_call) ss << "BEGIN_CALL";
|
else if(obj == _py_begin_call) ss << "BEGIN_CALL";
|
||||||
else if(obj == _py_null) ss << "NULL";
|
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 == None) ss << "None";
|
||||||
else if(obj == True) ss << "True";
|
else if(obj == True) ss << "True";
|
||||||
else if(obj == False) ss << "False";
|
else if(obj == False) ss << "False";
|
||||||
// else ss << obj << "(" << obj_type_name(this, obj->type) << ")";
|
else if(is_type(obj, tp_function)){
|
||||||
else ss << "(" << obj_type_name(this, obj->type) << ")";
|
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 << ", ";
|
ss << ", ";
|
||||||
}
|
}
|
||||||
std::string output = ss.str();
|
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, "()"));
|
if(!ok) TypeError(fmt(key.escape(), " is an invalid keyword argument for ", co->name, "()"));
|
||||||
}
|
}
|
||||||
PyObject* _module = fn._module != nullptr ? fn._module : top_frame()->_module;
|
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){
|
if(co->is_generator){
|
||||||
PyObject* ret = PyIter(Generator(this, Frame(&s_data, sp_base, co, _module, std::move(locals), fn._closure)));
|
PyObject* ret = PyIter(Generator(this, Frame(&s_data, curr_sp, co, _module, std::move(locals), fn._closure)));
|
||||||
s_data.reset(sp_base);
|
|
||||||
return ret;
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
## Function Tests.
|
## Function Tests.
|
||||||
|
|
||||||
|
|
||||||
def f1():
|
def f1():
|
||||||
return 'f1'
|
return 'f1'
|
||||||
assert f1() == 'f1'
|
assert f1() == 'f1'
|
||||||
@ -11,6 +10,11 @@ def f3(a,b):
|
|||||||
return a - b
|
return a - b
|
||||||
assert f3(1,2) == -1
|
assert f3(1,2) == -1
|
||||||
|
|
||||||
|
def f4(a,b):
|
||||||
|
return a + f3(a, b)
|
||||||
|
|
||||||
|
assert f4(1,2) == 0
|
||||||
|
|
||||||
def fact(n):
|
def fact(n):
|
||||||
if n == 1:
|
if n == 1:
|
||||||
return 1
|
return 1
|
||||||
@ -27,9 +31,23 @@ assert f(b=5) == 6
|
|||||||
assert f(a=5) == 4
|
assert f(a=5) == 4
|
||||||
assert f(b=5, a=5) == 10
|
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):
|
def f(a, b, *c, d=2, e=5):
|
||||||
return a + b + d + e + sum(c)
|
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) == 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, d=1, e=2) == 58
|
||||||
assert f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, e=1, d=2) == 58
|
assert f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, e=1, d=2) == 58
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user