Merge branch 'main' into c_binding_api

This commit is contained in:
Kolten Pearson 2023-05-02 22:09:34 -06:00
commit ed6d2fcad7
5 changed files with 52 additions and 37 deletions

View File

@ -408,22 +408,15 @@ __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());
#else
BaseIter* it = _PyIter_AS_C(TOP());
#endif
PyObject* obj = it->next();
if(obj != StopIteration){
PUSH(obj);
TARGET(FOR_ITER)
_0 = PyIterNext(TOP());
if(_0 != StopIteration){
PUSH(_0);
}else{
int target = co_blocks[byte.block].end;
frame->jump_abs_break(target);
frame->jump_abs_break(co_blocks[byte.block].end);
}
} DISPATCH();
DISPATCH();
/*****************************************/
TARGET(IMPORT_NAME) {
StrName name(byte.arg);
@ -459,12 +452,10 @@ __NEXT_STEP:;
/*****************************************/
TARGET(UNPACK_SEQUENCE)
TARGET(UNPACK_EX) {
// asIter or iter->next may run bytecode, accidential gc may happen
auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!!
PyObject* obj = asIter(POPX());
BaseIter* iter = PyIter_AS_C(obj);
PyObject* iter = asIter(POPX());
for(int i=0; i<byte.arg; i++){
PyObject* item = iter->next();
PyObject* item = PyIterNext(iter);
if(item == StopIteration) ValueError("not enough values to unpack");
PUSH(item);
}
@ -472,23 +463,22 @@ __NEXT_STEP:;
if(byte.op == OP_UNPACK_EX){
List extras;
while(true){
PyObject* item = iter->next();
PyObject* item = PyIterNext(iter);
if(item == StopIteration) break;
extras.push_back(item);
}
PUSH(VAR(extras));
}else{
if(iter->next() != StopIteration) ValueError("too many values to unpack");
if(PyIterNext(iter) != StopIteration) ValueError("too many values to unpack");
}
} DISPATCH();
TARGET(UNPACK_UNLIMITED) {
auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!!
PyObject* obj = asIter(POPX());
BaseIter* iter = PyIter_AS_C(obj);
obj = iter->next();
while(obj != StopIteration){
PUSH(obj);
obj = iter->next();
PyObject* iter = asIter(POPX());
_0 = PyIterNext(iter);
while(_0 != StopIteration){
PUSH(_0);
_0 = PyIterNext(iter);
}
} DISPATCH();
/*****************************************/

View File

@ -166,8 +166,7 @@ inline void init_builtins(VM* _vm) {
});
_vm->bind_builtin_func<1>("next", [](VM* vm, ArgsView args) {
BaseIter* iter = vm->PyIter_AS_C(args[0]);
return iter->next();
return vm->PyIterNext(args[0]);
});
_vm->bind_builtin_func<1>("dir", [](VM* vm, ArgsView args) {

View File

@ -383,6 +383,7 @@ const StrName __class__ = StrName::get("__class__");
const StrName __base__ = StrName::get("__base__");
const StrName __new__ = StrName::get("__new__");
const StrName __iter__ = StrName::get("__iter__");
const StrName __next__ = StrName::get("__next__");
const StrName __str__ = StrName::get("__str__");
const StrName __repr__ = StrName::get("__repr__");
const StrName __getitem__ = StrName::get("__getitem__");

View File

@ -80,6 +80,7 @@ public:
ValueStack s_data;
stack< Frame > callstack;
std::vector<PyTypeInfo> _all_types;
void (*_gc_marker_ex)(VM*) = nullptr;
NameDict _modules; // loaded modules
std::map<StrName, Str> _lazy_modules; // lazy loaded modules
@ -321,15 +322,12 @@ public:
return heap.gcnew<P>(tp_iterator, std::forward<P>(value));
}
BaseIter* PyIter_AS_C(PyObject* obj)
{
check_type(obj, tp_iterator);
return static_cast<BaseIter*>(obj->value());
}
BaseIter* _PyIter_AS_C(PyObject* obj)
{
return static_cast<BaseIter*>(obj->value());
PyObject* PyIterNext(PyObject* obj){
if(is_non_tagged_type(obj, tp_iterator)){
BaseIter* iter = static_cast<BaseIter*>(obj->value());
return iter->next();
}
return call_method(obj, __next__);
}
/***** Error Reporter *****/
@ -1017,7 +1015,7 @@ inline PyObject* VM::_py_call(PyObject** p0, PyObject* callable, ArgsView args,
// if this function is simple, a.k.a, no kwargs and no *args and not a generator
// we can use a fast path to avoid using buffer copy
if(fn.is_simple){
if(fn.is_simple && kwargs.size()==0){
if(args.size() > fn.decl->args.size()) TypeError("too many positional arguments");
int spaces = co->varnames.size() - fn.decl->args.size();
for(int j=0; j<spaces; j++) PUSH(nullptr);
@ -1194,6 +1192,7 @@ inline void ManagedHeap::mark() {
for(PyObject* obj: _no_gc) OBJ_MARK(obj);
for(auto& frame : vm->callstack.data()) frame._gc_mark();
for(PyObject* obj: vm->s_data) if(obj!=nullptr) OBJ_MARK(obj);
if(vm->_gc_marker_ex != nullptr) vm->_gc_marker_ex(vm);
}
inline Str obj_type_name(VM *vm, Type type){

View File

@ -10,3 +10,29 @@ while True:
total += obj
assert total == 6
class Task:
def __init__(self, n):
self.n = n
def __iter__(self):
self.i = 0
return self
def __next__(self):
if self.i == self.n:
return StopIteration
self.i += 1
return self.i
a = Task(3)
assert sum(a) == 6
i = iter(Task(5))
assert next(i) == 1
assert next(i) == 2
assert next(i) == 3
assert next(i) == 4
assert next(i) == 5
assert next(i) == StopIteration
assert next(i) == StopIteration