From dafaabfb84cc66718a55bfbcc4f5dda5402dc733 Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Tue, 25 Dec 2018 00:46:33 +0900 Subject: [PATCH] py: Support __len__ of rangetype. --- py/range.go | 47 +++++++++++++++++++++++++++++++++++++---------- py/tests/range.py | 16 ++++++++++++++++ 2 files changed, 53 insertions(+), 10 deletions(-) create mode 100644 py/tests/range.py diff --git a/py/range.go b/py/range.go index e91349f4..4dc0358e 100644 --- a/py/range.go +++ b/py/range.go @@ -9,10 +9,10 @@ package py // A python Range object // FIXME one day support BigInts too! type Range struct { - Start Int - Stop Int - Step Int - //Length Object + Start Int + Stop Int + Step Int + Length Int } // A python Range iterator @@ -53,10 +53,12 @@ func RangeNew(metatype *Type, args Tuple, kwargs StringDict) (Object, error) { return nil, err } if len(args) == 1 { + length := computeRangeLength(0, startIndex, 1) return &Range{ - Start: Int(0), - Stop: startIndex, - Step: Int(1), + Start: Int(0), + Stop: startIndex, + Step: Int(1), + Length: length, }, nil } stopIndex, err := Index(stop) @@ -67,10 +69,12 @@ func RangeNew(metatype *Type, args Tuple, kwargs StringDict) (Object, error) { if err != nil { return nil, err } + length := computeRangeLength(startIndex, stopIndex, stepIndex) return &Range{ - Start: startIndex, - Stop: stopIndex, - Step: stepIndex, + Start: startIndex, + Stop: stopIndex, + Step: stepIndex, + Length: length, }, nil } @@ -82,6 +86,10 @@ func (r *Range) M__iter__() (Object, error) { }, nil } +func (r *Range) M__len__() (Object, error) { + return r.Length, nil +} + // Range iterator func (it *RangeIterator) M__iter__() (Object, error) { return it, nil @@ -97,6 +105,25 @@ func (it *RangeIterator) M__next__() (Object, error) { return r, nil } +func computeRangeLength(start, stop, step Int) Int { + var lo, hi Int + if step > 0 { + lo = start + hi = stop + step = step + } else { + lo = stop + hi = start + step = (-step) + } + + if lo >= hi { + return Int(0) + } + res := (hi-lo-1)/step + 1 + return res +} + // Check interface is satisfied var _ I__iter__ = (*Range)(nil) var _ I_iterator = (*RangeIterator)(nil) diff --git a/py/tests/range.py b/py/tests/range.py new file mode 100644 index 00000000..327ecfa5 --- /dev/null +++ b/py/tests/range.py @@ -0,0 +1,16 @@ +# Copyright 2018 The go-python Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +doc="range" +a = range(255) +b = [e for e in a] +assert len(a) == len(b) +a = range(5, 100, 5) +b = [e for e in a] +assert len(a) == len(b) +a = range(100 ,0, 1) +b = [e for e in a] +assert len(a) == len(b) + +doc="finished"