From 8dba9194b0e84fe76a4842f1e8651585e871b5c4 Mon Sep 17 00:00:00 2001 From: Mansour Rahimi Date: Tue, 12 Sep 2017 07:29:49 +0200 Subject: [PATCH 1/2] Implement list.__delslice__ --- runtime/list.go | 47 ++++++++++++++++++++++++++++++++++++++++++++ runtime/list_test.go | 32 ++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/runtime/list.go b/runtime/list.go index 41e4c442..ac408758 100644 --- a/runtime/list.go +++ b/runtime/list.go @@ -228,6 +228,38 @@ 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") + } + l.mutex.Lock() + numListElems := len(l.elems) + start, raised := calcIndex(f, args[1], numListElems) + if raised != nil { + l.mutex.Unlock() + return nil, raised + } + stop, raised := calcIndex(f, args[2], numListElems) + if raised != nil { + l.mutex.Unlock() + return nil, raised + } + if start == stop || start > stop { + l.mutex.Unlock() + return nil, nil + } + numSliceElems := stop - start + copy(l.elems[start:numListElems-numSliceElems], l.elems[stop:numListElems]) + l.elems = l.elems[:numListElems-numSliceElems] + l.mutex.Unlock() + return nil, nil +} + 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 +553,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 +585,20 @@ func initListType(dict map[string]*Object) { ListType.slots.SetItem = &setItemSlot{listSetItem} } +func calcIndex(f *Frame, i *Object, numListElems int) (int, *BaseException) { + index, raised := IndexInt(f, i) + if raised != nil { + return 0, raised + } + if index < 0 { + index = 0 + } + if index > numListElems { + index = numListElems + } + return index, 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) { From 2e3bd49e6d3f3feed49f3aba9726793506a8bfcd Mon Sep 17 00:00:00 2001 From: Mansour Rahimi Date: Wed, 20 Sep 2017 07:20:55 +0200 Subject: [PATCH 2/2] Create slice and call list.DelSlice --- runtime/list.go | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/runtime/list.go b/runtime/list.go index ac408758..7e54c919 100644 --- a/runtime/list.go +++ b/runtime/list.go @@ -237,27 +237,18 @@ func listDelSlice(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) if args[1].typ.slots.Index == nil || args[2].typ.slots.Index == nil { return nil, f.RaiseType(TypeErrorType, "an integer is required") } - l.mutex.Lock() - numListElems := len(l.elems) - start, raised := calcIndex(f, args[1], numListElems) + s := &Slice{Object: Object{typ: SliceType}} + var raised *BaseException + s.start, raised = calcIndex(f, args[1]) if raised != nil { - l.mutex.Unlock() return nil, raised } - stop, raised := calcIndex(f, args[2], numListElems) + s.stop, raised = calcIndex(f, args[2]) if raised != nil { - l.mutex.Unlock() return nil, raised } - if start == stop || start > stop { - l.mutex.Unlock() - return nil, nil - } - numSliceElems := stop - start - copy(l.elems[start:numListElems-numSliceElems], l.elems[stop:numListElems]) - l.elems = l.elems[:numListElems-numSliceElems] - l.mutex.Unlock() - return nil, nil + s.step = NewInt(1).ToObject() + return nil, l.DelSlice(f, s) } func listRemove(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) { @@ -585,18 +576,15 @@ func initListType(dict map[string]*Object) { ListType.slots.SetItem = &setItemSlot{listSetItem} } -func calcIndex(f *Frame, i *Object, numListElems int) (int, *BaseException) { +func calcIndex(f *Frame, i *Object) (*Object, *BaseException) { index, raised := IndexInt(f, i) if raised != nil { - return 0, raised + return nil, raised } if index < 0 { index = 0 } - if index > numListElems { - index = numListElems - } - return index, nil + return NewInt(index).ToObject(), nil } type listIterator struct {