1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
from rpython.rtyper.lltypesystem.lltype import Ptr, GcStruct, Signed, malloc, Void
from rpython.rtyper.rrange import AbstractRangeRepr, AbstractRangeIteratorRepr
from rpython.rtyper.error import TyperError
# ____________________________________________________________
#
# Concrete implementation of RPython lists that are returned by range()
# and never mutated afterwards:
#
# struct range {
# Signed start, stop; // step is always constant
# }
#
# struct rangest {
# Signed start, stop, step; // rare case, for completeness
# }
def ll_length(l):
if l.step > 0:
lo = l.start
hi = l.stop
step = l.step
else:
lo = l.stop
hi = l.start
step = -l.step
if hi <= lo:
return 0
n = (hi - lo - 1) // step + 1
return n
def ll_getitem_fast(l, index):
return l.start + index * l.step
RANGEST = GcStruct("range", ("start", Signed), ("stop", Signed), ("step", Signed),
adtmeths = {
"ll_length":ll_length,
"ll_getitem_fast":ll_getitem_fast,
},
hints = {'immutable': True})
RANGESTITER = GcStruct("range", ("next", Signed), ("stop", Signed), ("step", Signed))
class RangeRepr(AbstractRangeRepr):
RANGEST = Ptr(RANGEST)
RANGESTITER = Ptr(RANGESTITER)
getfield_opname = "getfield"
def __init__(self, step, *args):
self.RANGE = Ptr(GcStruct("range", ("start", Signed), ("stop", Signed),
adtmeths = {
"ll_length":ll_length,
"ll_getitem_fast":ll_getitem_fast,
"step":step,
},
hints = {'immutable': True}))
self.RANGEITER = Ptr(GcStruct("range", ("next", Signed), ("stop", Signed)))
AbstractRangeRepr.__init__(self, step, *args)
self.ll_newrange = ll_newrange
self.ll_newrangest = ll_newrangest
def make_iterator_repr(self, variant=None):
if variant is not None:
raise TyperError("unsupported %r iterator over a range list" %
(variant,))
return RangeIteratorRepr(self)
def ll_newrange(RANGE, start, stop):
l = malloc(RANGE.TO)
l.start = start
l.stop = stop
return l
def ll_newrangest(start, stop, step):
if step == 0:
raise ValueError
l = malloc(RANGEST)
l.start = start
l.stop = stop
l.step = step
return l
class RangeIteratorRepr(AbstractRangeIteratorRepr):
def __init__(self, *args):
AbstractRangeIteratorRepr.__init__(self, *args)
self.ll_rangeiter = ll_rangeiter
def ll_rangeiter(ITERPTR, rng):
iter = malloc(ITERPTR.TO)
iter.next = rng.start
iter.stop = rng.stop
if ITERPTR.TO is RANGESTITER:
iter.step = rng.step
return iter
|