Commit 53d564e5 authored by YOU's avatar YOU Committed by Dylan Trotter

Implement list.pop (#117)

parent da545288
...@@ -291,6 +291,41 @@ func listNE(f *Frame, v, w *Object) (*Object, *BaseException) { ...@@ -291,6 +291,41 @@ func listNE(f *Frame, v, w *Object) (*Object, *BaseException) {
return listCompare(f, toListUnsafe(v), w, NE) return listCompare(f, toListUnsafe(v), w, NE)
} }
func listPop(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
argc := len(args)
expectedTypes := []*Type{ListType, ObjectType}
if argc == 1 {
expectedTypes = expectedTypes[:1]
}
if raised := checkMethodArgs(f, "pop", args, expectedTypes...); raised != nil {
return nil, raised
}
i := -1
if argc == 2 {
o, raised := IntType.Call(f, Args{args[1]}, nil)
if raised != nil {
return nil, raised
}
i = toIntUnsafe(o).Value()
}
l := toListUnsafe(args[0])
l.mutex.Lock()
numElems := len(l.elems)
if i < 0 {
i += numElems
}
var item *Object
var raised *BaseException
if i >= numElems || i < 0 {
raised = f.RaiseType(IndexErrorType, "list index out of range")
} else {
item = l.elems[i]
l.elems = append(l.elems[:i], l.elems[i+1:]...)
}
l.mutex.Unlock()
return item, raised
}
func listRepr(f *Frame, o *Object) (*Object, *BaseException) { func listRepr(f *Frame, o *Object) (*Object, *BaseException) {
l := toListUnsafe(o) l := toListUnsafe(o)
if f.reprEnter(l.ToObject()) { if f.reprEnter(l.ToObject()) {
...@@ -349,6 +384,7 @@ func listSort(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) { ...@@ -349,6 +384,7 @@ func listSort(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
func initListType(dict map[string]*Object) { func initListType(dict map[string]*Object) {
dict["append"] = newBuiltinFunction("append", listAppend).ToObject() dict["append"] = newBuiltinFunction("append", listAppend).ToObject()
dict["insert"] = newBuiltinFunction("insert", listInsert).ToObject() dict["insert"] = newBuiltinFunction("insert", listInsert).ToObject()
dict["pop"] = newBuiltinFunction("pop", listPop).ToObject()
dict["reverse"] = newBuiltinFunction("reverse", listReverse).ToObject() dict["reverse"] = newBuiltinFunction("reverse", listReverse).ToObject()
dict["sort"] = newBuiltinFunction("sort", listSort).ToObject() dict["sort"] = newBuiltinFunction("sort", listSort).ToObject()
ListType.slots.Add = &binaryOpSlot{listAdd} ListType.slots.Add = &binaryOpSlot{listAdd}
......
...@@ -353,6 +353,35 @@ func TestListIteratorIter(t *testing.T) { ...@@ -353,6 +353,35 @@ func TestListIteratorIter(t *testing.T) {
} }
} }
func TestListPop(t *testing.T) {
pop := mustNotRaise(GetAttr(NewRootFrame(), ListType.ToObject(), NewStr("pop"), nil))
fun := wrapFuncForTest(func(f *Frame, l *List, args ...*Object) (*Tuple, *BaseException) {
result, raised := pop.Call(f, append(Args{l.ToObject()}, args...), nil)
if raised != nil {
return nil, raised
}
return newTestTuple(result, l), nil
})
cases := []invokeTestCase{
{args: wrapArgs(newTestList(1)), want: newTestTuple(1, newTestList().ToObject()).ToObject()},
{args: wrapArgs(newTestList(1), 0), want: newTestTuple(1, newTestList().ToObject()).ToObject()},
{args: wrapArgs(newTestList(-1, 0, 1)), want: newTestTuple(1, newTestList(-1, 0).ToObject()).ToObject()},
{args: wrapArgs(newTestList(-1, 0, 1), 0), want: newTestTuple(-1, newTestList(0, 1).ToObject()).ToObject()},
{args: wrapArgs(newTestList(-1, 0, 1), NewLong(big.NewInt(1))), want: newTestTuple(0, newTestList(-1, 1).ToObject()).ToObject()},
{args: wrapArgs(newTestList(-1, 0, 1), None), wantExc: mustCreateException(TypeErrorType, "int() argument must be a string or a number, not 'NoneType'")},
{args: wrapArgs(newTestList(-1, 0, 1), None), wantExc: mustCreateException(TypeErrorType, "int() argument must be a string or a number, not 'NoneType'")},
{args: wrapArgs(newTestList(-1, 0, 1), 3), wantExc: mustCreateException(IndexErrorType, "list index out of range")},
{args: wrapArgs(newTestList()), wantExc: mustCreateException(IndexErrorType, "list index out of range")},
{args: wrapArgs(newTestList(), 0), wantExc: mustCreateException(IndexErrorType, "list index out of range")},
{args: wrapArgs(newTestList(), 1), wantExc: mustCreateException(IndexErrorType, "list index out of range")},
}
for _, cas := range cases {
if err := runInvokeTestCase(fun, &cas); err != "" {
t.Error(err)
}
}
}
func TestListSetItem(t *testing.T) { func TestListSetItem(t *testing.T) {
fun := newBuiltinFunction("TestListSetItem", func(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) { fun := newBuiltinFunction("TestListSetItem", func(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
// Check that there is at least one arg, but otherwise leave // Check that there is at least one arg, but otherwise leave
......
...@@ -40,3 +40,31 @@ b.sort() ...@@ -40,3 +40,31 @@ b.sort()
assert b == [] assert b == []
c.sort() c.sort()
assert c == ["a", "b", "c", "e"] assert c == ["a", "b", "c", "e"]
# Test pop
a = [-1, 0, 1]
assert a.pop() == 1
assert a == [-1, 0]
assert a == [-1, 0]
assert a.pop(0) == -1
assert a == [0]
try:
a.pop(5)
assert AssertionError
except IndexError:
pass
assert a.pop(0) == 0
assert a == []
try:
a.pop()
assert AssertionError
except IndexError:
pass
try:
a.pop(42, 42)
assert AssertionError
except TypeError:
pass
a = [-1, 0, 1]
assert a.pop(1) == 0
assert a == [-1, 1]
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment