Commit 2050551c authored by Meador Inge's avatar Meador Inge Committed by Dylan Trotter

Add support for the `any` builtin (#54) (#63)

Implement the `any` as defined here:

    * https://docs.python.org/2/library/functions.html#any

Note that a new helper function `seqFindFirst` was added that
is used to implement `builtinAll`, `builtinAny`, and `seqContains`.
parent 47e0e022
......@@ -194,25 +194,36 @@ func builtinAll(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
if raised := checkFunctionArgs(f, "all", args, ObjectType); raised != nil {
return nil, raised
}
iter, raised := Iter(f, args[0])
pred := func(o *Object) (bool, *BaseException) {
ret, raised := IsTrue(f, o)
if raised != nil {
return false, raised
}
return !ret, nil
}
foundFalseItem, raised := seqFindFirst(f, args[0], pred)
if raised != nil {
return nil, raised
}
o, raised := Next(f, iter)
for ; raised == nil; o, raised = Next(f, iter) {
return GetBool(!foundFalseItem).ToObject(), raised
}
func builtinAny(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
if raised := checkFunctionArgs(f, "any", args, ObjectType); raised != nil {
return nil, raised
}
pred := func(o *Object) (bool, *BaseException) {
ret, raised := IsTrue(f, o)
if raised != nil {
return nil, raised
}
if !ret {
return False.ToObject(), nil
return false, raised
}
return ret, nil
}
if !raised.isInstance(StopIterationType) {
foundTrueItem, raised := seqFindFirst(f, args[0], pred)
if raised != nil {
return nil, raised
}
f.RestoreExc(nil, nil)
return True.ToObject(), nil
return GetBool(foundTrueItem).ToObject(), raised
}
func builtinBin(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
......@@ -509,6 +520,7 @@ func init() {
"__frame__": newBuiltinFunction("__frame__", builtinFrame).ToObject(),
"abs": newBuiltinFunction("abs", builtinAbs).ToObject(),
"all": newBuiltinFunction("all", builtinAll).ToObject(),
"any": newBuiltinFunction("any", builtinAny).ToObject(),
"bin": newBuiltinFunction("bin", builtinBin).ToObject(),
"callable": newBuiltinFunction("callable", builtinCallable).ToObject(),
"chr": newBuiltinFunction("chr", builtinChr).ToObject(),
......
......@@ -92,6 +92,14 @@ func TestBuiltinFuncs(t *testing.T) {
{f: "all", args: wrapArgs(13), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
{f: "all", args: wrapArgs(newTestList(newObject(badNonZeroType))), wantExc: mustCreateException(RuntimeErrorType, "foo")},
{f: "all", args: wrapArgs(newObject(badIterType)), wantExc: mustCreateException(RuntimeErrorType, "foo")},
{f: "any", args: wrapArgs(newTestList()), want: False.ToObject()},
{f: "any", args: wrapArgs(newTestList(1, 2, 3)), want: True.ToObject()},
{f: "any", args: wrapArgs(newTestList(1, 0, 1)), want: True.ToObject()},
{f: "any", args: wrapArgs(newTestList(0, 0, 0)), want: False.ToObject()},
{f: "any", args: wrapArgs(newTestList(False.ToObject(), False.ToObject())), want: False.ToObject()},
{f: "any", args: wrapArgs(13), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
{f: "any", args: wrapArgs(newTestList(newObject(badNonZeroType))), wantExc: mustCreateException(RuntimeErrorType, "foo")},
{f: "any", args: wrapArgs(newObject(badIterType)), wantExc: mustCreateException(RuntimeErrorType, "foo")},
{f: "bin", args: wrapArgs(64 + 8 + 1), want: NewStr("0b1001001").ToObject()},
{f: "bin", args: wrapArgs(MinInt), want: NewStr(fmt.Sprintf("-0b%b0", -(MinInt >> 1))).ToObject()},
{f: "bin", args: wrapArgs(0), want: NewStr("0b0").ToObject()},
......
......@@ -162,7 +162,7 @@ func listAppend(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
}
func listContains(f *Frame, l, v *Object) (*Object, *BaseException) {
return seqContains(f, toListUnsafe(l).elems, v)
return seqContains(f, l, v)
}
func listEq(f *Frame, v, w *Object) (*Object, *BaseException) {
......
......@@ -108,21 +108,45 @@ func seqClampIndex(i, seqLen int) int {
return i
}
func seqContains(f *Frame, elems []*Object, v *Object) (*Object, *BaseException) {
for _, i := range elems {
eq, raised := Eq(f, v, i)
func seqContains(f *Frame, iterable *Object, v *Object) (*Object, *BaseException) {
pred := func(o *Object) (bool, *BaseException) {
eq, raised := Eq(f, v, o)
if raised != nil {
return nil, raised
return false, raised
}
ret, raised := IsTrue(f, eq)
if raised != nil {
return nil, raised
return false, raised
}
return ret, nil
}
foundEqItem, raised := seqFindFirst(f, iterable, pred)
if raised != nil {
return nil, raised
}
return GetBool(foundEqItem).ToObject(), raised
}
func seqFindFirst(f *Frame, iterable *Object, pred func(*Object) (bool, *BaseException)) (bool, *BaseException) {
iter, raised := Iter(f, iterable)
if raised != nil {
return false, raised
}
item, raised := Next(f, iter)
for ; raised == nil; item, raised = Next(f, iter) {
ret, raised := pred(item)
if raised != nil {
return false, raised
}
if ret {
return True.ToObject(), nil
return true, nil
}
}
return False.ToObject(), nil
if !raised.isInstance(StopIterationType) {
return false, raised
}
f.RestoreExc(nil, nil)
return false, nil
}
func seqForEach(f *Frame, iterable *Object, callback func(*Object) *BaseException) *BaseException {
......
......@@ -72,7 +72,7 @@ func tupleAdd(f *Frame, v, w *Object) (*Object, *BaseException) {
}
func tupleContains(f *Frame, t, v *Object) (*Object, *BaseException) {
return seqContains(f, toTupleUnsafe(t).elems, v)
return seqContains(f, t, v)
}
func tupleEq(f *Frame, v, w *Object) (*Object, *BaseException) {
......
......@@ -55,6 +55,29 @@ except TypeError as e:
else:
raise AssertionError('this was supposed to raise an exception')
# any(iterable)
assert any([1, 2, 3])
assert not any([])
assert any([1, 1, 1, 0, 1])
assert not any([0, 0, 0])
assert any([True, True])
assert any([False, True, True])
assert not any([False, False, False])
assert not any('')
assert any('abc')
try:
any(13)
except TypeError as e:
assert str(e) == "'int' object is not iterable"
else:
raise AssertionError('this was supposed to raise an exception')
# callable(x)
assert not callable(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