list.pop() is really useful

This commit is contained in:
K. Lange 2021-01-10 20:49:01 +09:00
parent fee817c3b7
commit 78c5503341
4 changed files with 62 additions and 7 deletions

View File

@ -5,6 +5,8 @@ const char krk_builtinsSrc[] =
" 'Resizable array with direct constant-time indexing.'\n" " 'Resizable array with direct constant-time indexing.'\n"
" def extend(i):\n" " def extend(i):\n"
" 'Add all entries from an iterable to the end of this list.'\n" " 'Add all entries from an iterable to the end of this list.'\n"
" if isinstance(i,list):\n"
" return self._extend_fast(i)\n"
" for v in i:\n" " for v in i:\n"
" self.append(v)\n" " self.append(v)\n"
" return self.__len__()\n" " return self.__len__()\n"

View File

@ -4,6 +4,8 @@ class list():
'Resizable array with direct constant-time indexing.' 'Resizable array with direct constant-time indexing.'
def extend(i): def extend(i):
'Add all entries from an iterable to the end of this list.' 'Add all entries from an iterable to the end of this list.'
if isinstance(i,list):
return self._extend_fast(i)
for v in i: for v in i:
self.append(v) self.append(v)
return self.__len__() return self.__len__()

View File

@ -41,15 +41,14 @@ for bag in descriptions.keys():
print("There are", count, "bags that can contain a shiny gold bag, eventually.") print("There are", count, "bags that can contain a shiny gold bag, eventually.")
def find_depth(bag): def find_depth(bag):
if not len(descriptions[bag]): if not descriptions[bag]:
return 0 return 0
let to_scan = descriptions[bag] let to_scan = descriptions[bag]
let count = 0 let count = 0
while len(to_scan): while to_scan:
let i = to_scan[0] let i = to_scan.pop(0)
to_scan = to_scan[1:]
count += 1 count += 1
to_scan.extend(descriptions[i]) to_scan._extend_fast(descriptions[i])
return count return count
print("A shiny gold bag contains", find_depth('shiny gold'), "bags.") print("A shiny gold bag contains", find_depth('shiny gold'), "bags.")

56
vm.c
View File

@ -478,6 +478,25 @@ static KrkValue _list_append(int argc, KrkValue argv[]) {
return NONE_VAL(); return NONE_VAL();
} }
/**
* list.extend but only for lists...
*/
static KrkValue _list_extend_fast(int argc, KrkValue argv[]) {
KrkValue _list_internal_self = OBJECT_VAL(AS_INSTANCE(argv[0])->_internal);
KrkValue _list_internal_them = OBJECT_VAL(AS_INSTANCE(argv[1])->_internal);
size_t totalSize = AS_LIST(_list_internal_self)->count + AS_LIST(_list_internal_them)->count;
if (AS_LIST(_list_internal_self)->capacity < totalSize) {
size_t old = AS_LIST(_list_internal_self)->capacity;
AS_LIST(_list_internal_self)->capacity = totalSize;
AS_LIST(_list_internal_self)->values = GROW_ARRAY(KrkValue, AS_LIST(_list_internal_self)->values, old, totalSize);
}
memcpy(&AS_LIST(_list_internal_self)->values[AS_LIST(_list_internal_self)->count],
AS_LIST(_list_internal_them)->values, sizeof(KrkValue) * AS_LIST(_list_internal_them)->count);
AS_LIST(_list_internal_self)->count = totalSize;
return INTEGER_VAL(totalSize);
}
/** /**
* list.__len__ * list.__len__
*/ */
@ -535,8 +554,12 @@ KrkValue krk_list_of(int argc, KrkValue argv[]) {
krk_tableSet(&outList->fields, vm.specialMethodNames[METHOD_LIST_INT], OBJECT_VAL(listContents)); krk_tableSet(&outList->fields, vm.specialMethodNames[METHOD_LIST_INT], OBJECT_VAL(listContents));
outList->_internal = (KrkObj*)listContents; outList->_internal = (KrkObj*)listContents;
krk_tableSet(&outList->fields, vm.specialMethodNames[METHOD_INREPR], INTEGER_VAL(0)); krk_tableSet(&outList->fields, vm.specialMethodNames[METHOD_INREPR], INTEGER_VAL(0));
for (int ind = 0; ind < argc; ++ind) {
krk_writeValueArray(&listContents->chunk.constants, argv[ind]); if (argc) {
listContents->chunk.constants.capacity = argc;
listContents->chunk.constants.values = GROW_ARRAY(KrkValue, listContents->chunk.constants.values, 0, argc);
memcpy(listContents->chunk.constants.values, argv, sizeof(KrkValue) * argc);
listContents->chunk.constants.count = argc;
} }
KrkValue out = OBJECT_VAL(outList); KrkValue out = OBJECT_VAL(outList);
krk_pop(); /* listContents */ krk_pop(); /* listContents */
@ -601,6 +624,33 @@ static KrkValue _list_slice(int argc, KrkValue argv[]) {
return krk_list_of(len, &AS_LIST(_list_internal)->values[start]); return krk_list_of(len, &AS_LIST(_list_internal)->values[start]);
} }
/**
* list.pop()
*/
static KrkValue _list_pop(int argc, KrkValue argv[]) {
long index = 0;
if (argc > 1) {
index = AS_INTEGER(argv[1]);
}
KrkValue _list_internal = OBJECT_VAL(AS_INSTANCE(argv[0])->_internal);
if (index < 0 || index >= (long)AS_LIST(_list_internal)->count) {
krk_runtimeError(vm.exceptions.indexError, "list index out of range: %d", (int)index);
return NONE_VAL();
}
KrkValue outItem = AS_LIST(_list_internal)->values[index];
if (index == (long)AS_LIST(_list_internal)->count-1) {
AS_LIST(_list_internal)->count--;
return outItem;
} else {
/* Need to move up */
size_t remaining = AS_LIST(_list_internal)->count - index - 1;
memmove(&AS_LIST(_list_internal)->values[index], &AS_LIST(_list_internal)->values[index+1],
sizeof(KrkValue) * remaining);
AS_LIST(_list_internal)->count--;
return outItem;
}
}
/** /**
* __builtins__.set_tracing(mode) * __builtins__.set_tracing(mode)
* *
@ -2788,6 +2838,8 @@ void krk_initVM(int flags) {
krk_defineNative(&_class->methods, ".__getslice__", _list_slice); krk_defineNative(&_class->methods, ".__getslice__", _list_slice);
krk_defineNative(&_class->methods, ".__iter__", _list_iter); krk_defineNative(&_class->methods, ".__iter__", _list_iter);
krk_defineNative(&_class->methods, ".append", _list_append); krk_defineNative(&_class->methods, ".append", _list_append);
krk_defineNative(&_class->methods, ".pop", _list_pop);
krk_defineNative(&_class->methods, "._extend_fast", _list_extend_fast);
krk_finalizeClass(_class); krk_finalizeClass(_class);
krk_tableGet(&vm.builtins->fields,OBJECT_VAL(S("dict")),&val); krk_tableGet(&vm.builtins->fields,OBJECT_VAL(S("dict")),&val);