From d1d815b295b53615fde7a0ce7b3e8f3e6754e458 Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Wed, 28 Jul 2021 19:32:49 +0900 Subject: [PATCH] Implement listiterators as C objects --- src/kuroko/util.h | 3 --- src/obj_list.c | 50 ++++++++++++++++++++++------------------------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/src/kuroko/util.h b/src/kuroko/util.h index b1f76fa..8d25e3a 100644 --- a/src/kuroko/util.h +++ b/src/kuroko/util.h @@ -192,9 +192,6 @@ static inline KrkValue discardStringBuilder(struct StringBuilder * sb) { #define IS_class(o) IS_CLASS(o) #define AS_class(o) AS_CLASS(o) -#define IS_listiterator(o) krk_isInstanceOf(o,vm.baseClasses->listiteratorClass) -#define AS_listiterator(o) AS_INSTANCE(o) - #define IS_str(o) (IS_STRING(o)||krk_isInstanceOf(o,vm.baseClasses->strClass)) #define AS_str(o) (KrkString*)AS_OBJECT(o) diff --git a/src/obj_list.c b/src/obj_list.c index db2c25b..a8d171b 100644 --- a/src/obj_list.c +++ b/src/obj_list.c @@ -411,46 +411,40 @@ KRK_METHOD(list,__iter__,{ }) #undef CURRENT_CTYPE -#define CURRENT_CTYPE KrkInstance* + +struct ListIterator { + KrkInstance inst; + KrkValue l; + size_t i; +}; + +#define CURRENT_CTYPE struct ListIterator * +#define IS_listiterator(o) krk_isInstanceOf(o,vm.baseClasses->listiteratorClass) +#define AS_listiterator(o) (struct ListIterator*)AS_OBJECT(o) + +static void _listiterator_gcscan(KrkInstance * self) { + krk_markValue(((struct ListIterator*)self)->l); +} KRK_METHOD(listiterator,__init__,{ METHOD_TAKES_EXACTLY(1); CHECK_ARG(1,list,KrkList*,list); - - krk_push(argv[0]); - krk_attachNamedValue(&self->fields, "l", OBJECT_VAL(list)); - krk_attachNamedValue(&self->fields, "i", INTEGER_VAL(0)); - krk_pop(); - + self->l = argv[1]; + self->i = 0; return argv[0]; }) KRK_METHOD(listiterator,__call__,{ - KrkValue _list; - KrkValue _counter; - const char * errorStr = NULL; - - if (!krk_tableGet(&self->fields, OBJECT_VAL(S("l")), &_list)) { - errorStr = "no list pointer"; - goto _corrupt; - } - if (!krk_tableGet(&self->fields, OBJECT_VAL(S("i")), &_counter)) { - errorStr = "no index"; - goto _corrupt; - } - - if ((size_t)AS_INTEGER(_counter) >= AS_LIST(_list)->count) { + KrkValue _list = self->l; + size_t _counter = self->i; + if (_counter >= AS_LIST(_list)->count) { return argv[0]; } else { - krk_attachNamedValue(&self->fields, "i", INTEGER_VAL(AS_INTEGER(_counter)+1)); - return AS_LIST(_list)->values[AS_INTEGER(_counter)]; + self->i = _counter + 1; + return AS_LIST(_list)->values[_counter]; } - -_corrupt: - return krk_runtimeError(vm.exceptions->typeError, "Corrupt list iterator: %s", errorStr); }) - static KrkValue _sorted(int argc, KrkValue argv[], int hasKw) { if (argc != 1) return krk_runtimeError(vm.exceptions->argumentError,"%s() takes %s %d argument%s (%d given)","sorted","exactly",1,"",argc); KrkValue listOut = krk_list_of(0,NULL,0); @@ -565,6 +559,8 @@ void _createAndBind_listClass(void) { "Creates a new, reversed list from the elements of @p iterable."); KrkClass * listiterator = ADD_BASE_CLASS(vm.baseClasses->listiteratorClass, "listiterator", vm.baseClasses->objectClass); + listiterator->allocSize = sizeof(struct ListIterator); + listiterator->_ongcscan = _listiterator_gcscan; BIND_METHOD(listiterator,__init__); BIND_METHOD(listiterator,__call__); krk_finalizeClass(listiterator);