diff --git a/runtime/list.go b/runtime/list.go index 41e4c442..7e54c919 100644 --- a/runtime/list.go +++ b/runtime/list.go @@ -228,6 +228,29 @@ func listDelItem(f *Frame, o *Object, key *Object) *BaseException { return l.DelItem(f, index) } +func listDelSlice(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) { + argc := len(args) + if argc != 3 { + return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("function takes exactly 2 arguments (%d given)", argc-1)) + } + l := toListUnsafe(args[0]) + if args[1].typ.slots.Index == nil || args[2].typ.slots.Index == nil { + return nil, f.RaiseType(TypeErrorType, "an integer is required") + } + s := &Slice{Object: Object{typ: SliceType}} + var raised *BaseException + s.start, raised = calcIndex(f, args[1]) + if raised != nil { + return nil, raised + } + s.stop, raised = calcIndex(f, args[2]) + if raised != nil { + return nil, raised + } + s.step = NewInt(1).ToObject() + return nil, l.DelSlice(f, s) +} + func listRemove(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) { if raised := checkMethodArgs(f, "remove", args, ListType, ObjectType); raised != nil { return nil, raised @@ -521,6 +544,7 @@ func listSort(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) { } func initListType(dict map[string]*Object) { + dict["__delslice__"] = newBuiltinFunction("__delslice__", listDelSlice).ToObject() dict["append"] = newBuiltinFunction("append", listAppend).ToObject() dict["count"] = newBuiltinFunction("count", listCount).ToObject() dict["extend"] = newBuiltinFunction("extend", listExtend).ToObject() @@ -552,6 +576,17 @@ func initListType(dict map[string]*Object) { ListType.slots.SetItem = &setItemSlot{listSetItem} } +func calcIndex(f *Frame, i *Object) (*Object, *BaseException) { + index, raised := IndexInt(f, i) + if raised != nil { + return nil, raised + } + if index < 0 { + index = 0 + } + return NewInt(index).ToObject(), nil +} + type listIterator struct { Object list *List diff --git a/runtime/list_test.go b/runtime/list_test.go index 3b29a2c4..350195a5 100644 --- a/runtime/list_test.go +++ b/runtime/list_test.go @@ -92,6 +92,38 @@ func TestListCount(t *testing.T) { } } +func TestListDelSlice(t *testing.T) { + fun := newBuiltinFunction("TestListDelSlice", func(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) { + delSlice, raised := GetAttr(f, ListType.ToObject(), NewStr("__delslice__"), nil) + if raised != nil { + return nil, raised + } + if _, raised := delSlice.Call(f, args, nil); raised != nil { + return nil, raised + } + return args[0], nil + }).ToObject() + cases := []invokeTestCase{ + {args: wrapArgs(NewList(), 1, 3), want: NewList().ToObject()}, + {args: wrapArgs(newTestList(1, 2, 3, 4, 5), -1, 3), want: newTestList(4, 5).ToObject()}, + {args: wrapArgs(newTestList(1, 2, 3, 4, 5), 1, -3), want: newTestList(1, 2, 3, 4, 5).ToObject()}, + {args: wrapArgs(newTestList(1, 2, 3, 4, 5), -1, -3), want: newTestList(1, 2, 3, 4, 5).ToObject()}, + {args: wrapArgs(newTestList(1, 2, 3, 4, 5), 3, 3), want: newTestList(1, 2, 3, 4, 5).ToObject()}, + {args: wrapArgs(newTestList(1, 2, 3, 4, 5), 1, 3), want: newTestList(1, 4, 5).ToObject()}, + {args: wrapArgs(newTestList(1, 2, 3, 4, 5), 1, big.NewInt(3)), want: newTestList(1, 4, 5).ToObject()}, + {args: wrapArgs(newTestList(1, 2, 3, 4, 5), 1, 31415), want: newTestList(1).ToObject()}, + {args: wrapArgs(newTestList(1, 2, 3, 4, 5), 3, 1), want: newTestList(1, 2, 3, 4, 5).ToObject()}, + {args: wrapArgs(newTestRange(10), 1, 8), want: newTestList(0, 8, 9).ToObject()}, + {args: wrapArgs(NewList(), 1), wantExc: mustCreateException(TypeErrorType, "function takes exactly 2 arguments (1 given)")}, + {args: wrapArgs(newTestList(true), None, None), wantExc: mustCreateException(TypeErrorType, "an integer is required")}, + } + for _, cas := range cases { + if err := runInvokeTestCase(fun, &cas); err != "" { + t.Error(err) + } + } +} + func TestListDelItem(t *testing.T) { badIndexType := newTestClass("badIndex", []*Type{ObjectType}, newStringDict(map[string]*Object{ "__index__": newBuiltinFunction("__index__", func(f *Frame, _ Args, _ KWArgs) (*Object, *BaseException) {