From 437c89770660491ed893140a5962ec28cbce2a2d Mon Sep 17 00:00:00 2001 From: Meador Inge Date: Thu, 5 Jan 2017 21:38:43 -0600 Subject: [PATCH] Add support for the `all` builtin Implement the `all` as defined here: * https://docs.python.org/2/library/functions.html#all --- runtime/builtin_types.go | 26 ++++++++++++++++++++++++++ runtime/builtin_types_test.go | 21 +++++++++++++++++++++ testing/builtin_test.py | 20 ++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/runtime/builtin_types.go b/runtime/builtin_types.go index a64caa53..9ae8a0dc 100644 --- a/runtime/builtin_types.go +++ b/runtime/builtin_types.go @@ -190,6 +190,31 @@ func builtinAbs(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) { return Abs(f, args[0]) } +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]) + if raised != nil { + return nil, raised + } + o, raised := Next(f, iter) + for ; raised == nil; o, raised = Next(f, iter) { + ret, raised := IsTrue(f, o) + if raised != nil { + return nil, raised + } + if !ret { + return False.ToObject(), nil + } + } + if !raised.isInstance(StopIterationType) { + return nil, raised + } + f.RestoreExc(nil, nil) + return True.ToObject(), nil +} + func builtinBin(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) { if raised := checkFunctionArgs(f, "bin", args, ObjectType); raised != nil { return nil, raised @@ -472,6 +497,7 @@ func init() { builtinMap := map[string]*Object{ "__frame__": newBuiltinFunction("__frame__", builtinFrame).ToObject(), "abs": newBuiltinFunction("abs", builtinAbs).ToObject(), + "all": newBuiltinFunction("all", builtinAll).ToObject(), "bin": newBuiltinFunction("bin", builtinBin).ToObject(), "chr": newBuiltinFunction("chr", builtinChr).ToObject(), "dir": newBuiltinFunction("dir", builtinDir).ToObject(), diff --git a/runtime/builtin_types_test.go b/runtime/builtin_types_test.go index 1eaa0cc1..d5c780d0 100644 --- a/runtime/builtin_types_test.go +++ b/runtime/builtin_types_test.go @@ -49,6 +49,21 @@ func TestBuiltinFuncs(t *testing.T) { return NewInt(123).ToObject(), nil }).ToObject(), })) + badNonZeroType := newTestClass("BadNonZeroType", []*Type{ObjectType}, newStringDict(map[string]*Object{ + "__nonzero__": newBuiltinFunction("__nonzero__", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) { + return nil, f.RaiseType(RuntimeErrorType, "foo") + }).ToObject(), + })) + badNextType := newTestClass("BadNextType", []*Type{ObjectType}, newStringDict(map[string]*Object{ + "next": newBuiltinFunction("next", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) { + return nil, f.RaiseType(RuntimeErrorType, "foo") + }).ToObject(), + })) + badIterType := newTestClass("BadIterType", []*Type{ObjectType}, newStringDict(map[string]*Object{ + "__iter__": newBuiltinFunction("__iter__", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) { + return newObject(badNextType), nil + }).ToObject(), + })) cases := []struct { f string args Args @@ -65,6 +80,12 @@ func TestBuiltinFuncs(t *testing.T) { {f: "abs", args: wrapArgs(NewFloat(-3.4)), want: NewFloat(3.4).ToObject()}, {f: "abs", args: wrapArgs(MinInt), want: NewLong(big.NewInt(MinInt).Neg(minIntBig)).ToObject()}, {f: "abs", args: wrapArgs(NewStr("a")), wantExc: mustCreateException(TypeErrorType, "bad operand type for abs(): 'str'")}, + {f: "all", args: wrapArgs(newTestList()), want: True.ToObject()}, + {f: "all", args: wrapArgs(newTestList(1, 2, 3)), want: True.ToObject()}, + {f: "all", args: wrapArgs(newTestList(1, 0, 1)), want: False.ToObject()}, + {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: "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()}, diff --git a/testing/builtin_test.py b/testing/builtin_test.py index 81d22bce..3195b7dc 100644 --- a/testing/builtin_test.py +++ b/testing/builtin_test.py @@ -34,3 +34,23 @@ assert str(e) == "bad operand type for abs(): 'str'" else: raise AssertionError('this was supposed to raise an exception') + + +# all(iterable) + +assert all([1, 2, 3]) +assert all([]) +assert not all([1, 1, 1, 0, 1]) + +assert all([True, True]) +assert not all([False, True, True]) + +assert all('') +assert all('abc') + +try: + all(13) +except TypeError as e: + assert str(e) == "'int' object is not iterable" +else: + raise AssertionError('this was supposed to raise an exception')