List slicing and a gc fix for iterators
This commit is contained in:
parent
bfae38538d
commit
8f2e7f237e
89
vm.c
89
vm.c
@ -332,6 +332,7 @@ static KrkValue _list_get(int argc, KrkValue argv[]) {
|
||||
KrkValue _list_internal;
|
||||
krk_tableGet(&AS_INSTANCE(argv[0])->fields, vm.specialMethodNames[METHOD_LIST_INT], &_list_internal);
|
||||
int index = AS_INTEGER(argv[1]);
|
||||
if (index < 0) index += AS_LIST(_list_internal)->count;
|
||||
if (index < 0 || index >= (int)AS_LIST(_list_internal)->count) {
|
||||
krk_runtimeError(vm.exceptions.indexError, "index is out of range: %d", index);
|
||||
return NONE_VAL();
|
||||
@ -350,6 +351,7 @@ static KrkValue _list_set(int argc, KrkValue argv[]) {
|
||||
KrkValue _list_internal;
|
||||
krk_tableGet(&AS_INSTANCE(argv[0])->fields, vm.specialMethodNames[METHOD_LIST_INT], &_list_internal);
|
||||
int index = AS_INTEGER(argv[1]);
|
||||
if (index < 0) index += AS_LIST(_list_internal)->count;
|
||||
if (index < 0 || index >= (int)AS_LIST(_list_internal)->count) {
|
||||
krk_runtimeError(vm.exceptions.indexError, "index is out of range: %d", index);
|
||||
return NONE_VAL();
|
||||
@ -465,6 +467,37 @@ KrkValue krk_dict_of(int argc, KrkValue argv[]) {
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* list.__getslice__
|
||||
*/
|
||||
static KrkValue _list_slice(int argc, KrkValue argv[]) {
|
||||
if (argc < 3) { /* 3 because first is us */
|
||||
krk_runtimeError(vm.exceptions.argumentError, "slice: expected 2 arguments, got %d", argc-1);
|
||||
return NONE_VAL();
|
||||
}
|
||||
if (!IS_INSTANCE(argv[0]) ||
|
||||
!(IS_INTEGER(argv[1]) || IS_NONE(argv[1])) ||
|
||||
!(IS_INTEGER(argv[2]) || IS_NONE(argv[2]))) {
|
||||
krk_runtimeError(vm.exceptions.typeError, "slice: expected two integer arguments");
|
||||
return NONE_VAL();
|
||||
}
|
||||
|
||||
KrkValue _list_internal;
|
||||
krk_tableGet(&AS_INSTANCE(argv[0])->fields, vm.specialMethodNames[METHOD_LIST_INT], &_list_internal);
|
||||
|
||||
int start = IS_NONE(argv[1]) ? 0 : AS_INTEGER(argv[1]);
|
||||
int end = IS_NONE(argv[2]) ? (int)AS_LIST(_list_internal)->count : AS_INTEGER(argv[2]);
|
||||
if (start < 0) start = (int)AS_LIST(_list_internal)->count + start;
|
||||
if (start < 0) start = 0;
|
||||
if (end < 0) end = (int)AS_LIST(_list_internal)->count + end;
|
||||
if (start > (int)AS_LIST(_list_internal)->count) start = (int)AS_LIST(_list_internal)->count;
|
||||
if (end > (int)AS_LIST(_list_internal)->count) end = (int)AS_LIST(_list_internal)->count;
|
||||
if (end < start) end = start;
|
||||
int len = end - start;
|
||||
|
||||
return krk_list_of(len, &AS_LIST(_list_internal)->values[start]);
|
||||
}
|
||||
|
||||
/**
|
||||
* __builtins__.set_tracing(mode)
|
||||
*
|
||||
@ -1894,34 +1927,55 @@ static KrkValue _repr(int argc, KrkValue argv[]) {
|
||||
}
|
||||
|
||||
static KrkValue _listiter_init(int argc, KrkValue argv[]) {
|
||||
if (!IS_INSTANCE(argv[0]) || AS_INSTANCE(argv[0])->_class != vm.baseClasses.listiteratorClass) {
|
||||
krk_runtimeError(vm.exceptions.typeError, "Tried to call listiterator.__init__() on something not a list iterator");
|
||||
}
|
||||
if (argc < 2 || !IS_INSTANCE(argv[1])) {
|
||||
krk_runtimeError(vm.exceptions.argumentError, "Expected a list.");
|
||||
}
|
||||
KrkInstance * self = AS_INSTANCE(argv[0]);
|
||||
KrkValue _list = argv[1];
|
||||
|
||||
krk_tableSet(&self->fields, OBJECT_VAL(S("l")), _list);
|
||||
krk_tableSet(&self->fields, OBJECT_VAL(S("i")), INTEGER_VAL(0));
|
||||
krk_push(argv[0]);
|
||||
krk_attachNamedValue(&self->fields, "l", _list);
|
||||
krk_attachNamedValue(&self->fields, "i", INTEGER_VAL(0));
|
||||
krk_pop();
|
||||
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static KrkValue _listiter_call(int argc, KrkValue argv[]) {
|
||||
if (!IS_INSTANCE(argv[0]) || AS_INSTANCE(argv[0])->_class != vm.baseClasses.listiteratorClass) {
|
||||
krk_runtimeError(vm.exceptions.typeError, "Tried to call listiterator.__call__() on something not a list iterator");
|
||||
}
|
||||
KrkInstance * self = AS_INSTANCE(argv[0]);
|
||||
KrkValue _list;
|
||||
KrkValue _counter;
|
||||
KrkValue _list_internal;
|
||||
const char * errorStr = NULL;
|
||||
|
||||
if (!krk_tableGet(&self->fields, OBJECT_VAL(S("l")), &_list)) goto _corrupt;
|
||||
if (!krk_tableGet(&self->fields, OBJECT_VAL(S("i")), &_counter)) goto _corrupt;
|
||||
if (!krk_tableGet(&AS_INSTANCE(_list)->fields, vm.specialMethodNames[METHOD_LIST_INT], &_list_internal)) goto _corrupt;
|
||||
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 (!krk_tableGet(&AS_INSTANCE(_list)->fields, vm.specialMethodNames[METHOD_LIST_INT], &_list_internal)) {
|
||||
errorStr = "failed to obtain __list from list";
|
||||
goto _corrupt;
|
||||
}
|
||||
|
||||
if ((size_t)AS_INTEGER(_counter) >= AS_LIST(_list_internal)->count) {
|
||||
return argv[0];
|
||||
} else {
|
||||
krk_tableSet(&self->fields, OBJECT_VAL(S("i")), INTEGER_VAL(AS_INTEGER(_counter)+1));
|
||||
krk_attachNamedValue(&self->fields, "i", INTEGER_VAL(AS_INTEGER(_counter)+1));
|
||||
return AS_LIST(_list_internal)->values[AS_INTEGER(_counter)];
|
||||
}
|
||||
|
||||
_corrupt:
|
||||
krk_runtimeError(vm.exceptions.typeError, "Corrupt list iterator");
|
||||
krk_runtimeError(vm.exceptions.typeError, "Corrupt list iterator: %s", errorStr);
|
||||
return NONE_VAL();
|
||||
}
|
||||
|
||||
@ -1949,8 +2003,10 @@ static KrkValue _range_init(int argc, KrkValue argv[]) {
|
||||
}
|
||||
|
||||
/* Add them to ourselves */
|
||||
krk_tableSet(&self->fields, OBJECT_VAL(S("min")), min);
|
||||
krk_tableSet(&self->fields, OBJECT_VAL(S("max")), max);
|
||||
krk_push(argv[0]);
|
||||
krk_attachNamedValue(&self->fields, "min", min);
|
||||
krk_attachNamedValue(&self->fields, "max", max);
|
||||
krk_pop();
|
||||
|
||||
return argv[0];
|
||||
}
|
||||
@ -1970,8 +2026,10 @@ static KrkValue _range_repr(int argc, KrkValue argv[]) {
|
||||
|
||||
static KrkValue _rangeiterator_init(int argc, KrkValue argv[]) {
|
||||
KrkInstance * self = AS_INSTANCE(argv[0]);
|
||||
krk_tableSet(&self->fields, OBJECT_VAL(S("i")), argv[1]);
|
||||
krk_tableSet(&self->fields, OBJECT_VAL(S("m")), argv[2]);
|
||||
krk_push(argv[0]);
|
||||
krk_attachNamedValue(&self->fields, "i", argv[1]);
|
||||
krk_attachNamedValue(&self->fields, "m", argv[2]);
|
||||
krk_pop();
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
@ -1983,7 +2041,7 @@ static KrkValue _rangeiterator_call(int argc, KrkValue argv[]) {
|
||||
if (AS_INTEGER(i) >= AS_INTEGER(m)) {
|
||||
return argv[0];
|
||||
} else {
|
||||
krk_tableSet(&self->fields, OBJECT_VAL(S("i")), INTEGER_VAL(AS_INTEGER(i)+1));
|
||||
krk_attachNamedValue(&self->fields, "i", INTEGER_VAL(AS_INTEGER(i)+1));
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@ -2180,6 +2238,7 @@ void krk_initVM(int flags) {
|
||||
krk_defineNative(&_class->methods, ".__set__", _list_set);
|
||||
krk_defineNative(&_class->methods, ".__len__", _list_len);
|
||||
krk_defineNative(&_class->methods, ".__contains__", _list_contains);
|
||||
krk_defineNative(&_class->methods, ".__getslice__", _list_slice);
|
||||
krk_defineNative(&_class->methods, ".append", _list_append);
|
||||
|
||||
krk_tableGet(&vm.globals,OBJECT_VAL(S("dict")),&val);
|
||||
@ -2852,7 +2911,7 @@ static KrkValue run() {
|
||||
krk_pop(); /* base object */
|
||||
krk_push(out); /* result */
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions.attributeError, "'%s' object is not subscriptable", krk_typeName(krk_peek(0)));
|
||||
krk_runtimeError(vm.exceptions.attributeError, "'%s' object is not subscriptable", krk_typeName(krk_peek(1)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2863,7 +2922,7 @@ static KrkValue run() {
|
||||
_strings_are_immutable(0,NULL);
|
||||
goto _finishException;
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions.attributeError, "'%s' object is not subscriptable", krk_typeName(krk_peek(0)));
|
||||
krk_runtimeError(vm.exceptions.attributeError, "'%s' object is not subscriptable", krk_typeName(krk_peek(2)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2877,7 +2936,7 @@ static KrkValue run() {
|
||||
krk_pop(); /* base object */
|
||||
krk_push(out); /* result */
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions.attributeError, "'%s' object is not sliceable", krk_typeName(krk_peek(0)));
|
||||
krk_runtimeError(vm.exceptions.attributeError, "'%s' object is not sliceable", krk_typeName(krk_peek(2)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user