<commit_before>"A [[Range]] of adjacent [[Enumerable]] values generated by 
 two endpoints: [[first]] and [[last]]. The range includes 
 both endpoints, and all values falling _between_ the 
 endpoints."
by ("Gavin")
see (`class Measure`,
    `interface Enumerable`)
final serializable
class Span<Element>(first, last)
        extends Range<Element>()
        given Element satisfies Enumerable<Element> {
    
    "The start of the range."
    shared actual Element first;
    
    "The end of the range."
    shared actual Element last;
    
    string => first.string + ".." + last.string;
    
    increasing = last.offsetSign(first) >= 0;
    
    decreasing => !increasing;
    
    "Determines if the range is of recursive values, that 
     is, if successors wrap back on themselves. All 
     recursive ranges are [[increasing]]."
    Boolean recursive
            = first.offsetSign(first.successor) > 0 &&
              last.predecessor.offsetSign(last) > 0;
    
    Element next(Element x)
            => increasing 
            then x.successor
            else x.predecessor;
    
    Element nextStep(Element x, Integer step)
            => increasing 
            then x.neighbour(step)
            else x.neighbour(-step);
    
    Element fromFirst(Integer offset)
            => increasing 
            then first.neighbour(offset)
            else first.neighbour(-offset);
    
    Boolean afterLast(Element x)
            => increasing 
            then x.offsetSign(last) > 0
            else x.offsetSign(last) < 0;
    
    Boolean beforeLast(Element x)
            => increasing 
            then x.offsetSign(last) < 0
            else x.offsetSign(last) > 0;
    
    Boolean beforeFirst(Element x)
            => increasing 
            then x.offsetSign(first) < 0
            else x.offsetSign(first) > 0;
    
    Boolean afterFirst(Element x)
            => increasing 
            then x.offsetSign(first) > 0
            else x.offsetSign(first) < 0;
    
    shared actual Integer size {
        value lastIndex = last.offset(first).magnitude;
        if (lastIndex<runtime.maxIntegerValue) {
            return lastIndex + 1;
        }
        else {
            throw OverflowException("size of range");
        }
    }
    
    longerThan(Integer length) 
            => if (length < 1) then true
            else if (recursive) then size > length
            else beforeLast(fromFirst(length - 1));
    
    shorterThan(Integer length)
            => if (length < 1) then true
            else if (recursive) then size < length
            else afterLast(fromFirst(length - 1));
    
    lastIndex => size - 1;
    
    rest => first == last then [] else next(first)..last;
    
    "This range in reverse, with [[first]] and [[last]]
     interchanged.
     
     For any two range endpoints, `x` and `y`: 
     
         `(x..y).reversed == y..x`
     
     except for [[recursive]] ranges, where the elements are
     evaluated and collected into a new sequence."
    //TODO: we should have a way to produce a decreasing
    //      recursive range
    shared actual 
    [Element+] reversed
            => recursive 
            then super.reversed
            else last..first;
    
    "The element of the range that occurs [[index]] values 
     after the start of the range."
    shared actual 
    Element? getFromFirst(Integer index) {
        if (index < 0) {
            return null;
        } else if (recursive) {
            return index < size then fromFirst(index);
        } else {
            value result = fromFirst(index);
            return !afterLast(result) then result;
        }
    }
    
    "An iterator for the elements of the range. The returned 
     iterator produces elements from [[first]] and continues 
     producing elements until it reaches an element whose 
     `offset` from [[last] is zero."
    shared actual 
    Iterator<Element> iterator() 
            => object
            satisfies Iterator<Element> {
        variable Element|Finished current = first;
        shared actual Element|Finished next() {
            if (!is Finished c = current) {
                if (c.offset(last) != 0) {
                    value result = c;
                    this.current = outer.next(c);
                    return result;
                } else {
                    value result = c;
                    this.current = finished;
                    return result;
                }
            } else {
                return current;
            }
        }
        string => "(``outer``).iterator()";
    };
    
    shared actual 
    {Element+} by(Integer step) {
        "step size must be greater than zero"
        assert (step > 0);
        return step == 1 then this else By(step);
    }
    
    shifted(Integer shift)
            => shift == 0
            then this
            else Span(first.neighbour(shift), 
                      last.neighbour(shift));
    
    containsElement(Element x)<commit_msg>ceylon/ceylon-compiler#2130: Rewrite Span.iterator so we compute the next in the same invocation as we return it. Previously the current invocation computed the next invocations result. That produced incorrect results when that computation overflowed (e.g. iterating up to the last Character).<commit_after>"A [[Range]] of adjacent [[Enumerable]] values generated by 
 two endpoints: [[first]] and [[last]]. The range includes 
 both endpoints, and all values falling _between_ the 
 endpoints."
by ("Gavin")
see (`class Measure`,
    `interface Enumerable`)
final serializable
class Span<Element>(first, last)
        extends Range<Element>()
        given Element satisfies Enumerable<Element> {
    
    "The start of the range."
    shared actual Element first;
    
    "The end of the range."
    shared actual Element last;
    
    string => first.string + ".." + last.string;
    
    increasing = last.offsetSign(first) >= 0;
    
    decreasing => !increasing;
    
    "Determines if the range is of recursive values, that 
     is, if successors wrap back on themselves. All 
     recursive ranges are [[increasing]]."
    Boolean recursive
            = first.offsetSign(first.successor) > 0 &&
              last.predecessor.offsetSign(last) > 0;
    
    Element next(Element x)
            => increasing 
            then x.successor
            else x.predecessor;
    
    Element nextStep(Element x, Integer step)
            => increasing 
            then x.neighbour(step)
            else x.neighbour(-step);
    
    Element fromFirst(Integer offset)
            => increasing 
            then first.neighbour(offset)
            else first.neighbour(-offset);
    
    Boolean afterLast(Element x)
            => increasing 
            then x.offsetSign(last) > 0
            else x.offsetSign(last) < 0;
    
    Boolean beforeLast(Element x)
            => increasing 
            then x.offsetSign(last) < 0
            else x.offsetSign(last) > 0;
    
    Boolean beforeFirst(Element x)
            => increasing 
            then x.offsetSign(first) < 0
            else x.offsetSign(first) > 0;
    
    Boolean afterFirst(Element x)
            => increasing 
            then x.offsetSign(first) > 0
            else x.offsetSign(first) < 0;
    
    shared actual Integer size {
        value lastIndex = last.offset(first).magnitude;
        if (lastIndex<runtime.maxIntegerValue) {
            return lastIndex + 1;
        }
        else {
            throw OverflowException("size of range");
        }
    }
    
    longerThan(Integer length) 
            => if (length < 1) then true
            else if (recursive) then size > length
            else beforeLast(fromFirst(length - 1));
    
    shorterThan(Integer length)
            => if (length < 1) then true
            else if (recursive) then size < length
            else afterLast(fromFirst(length - 1));
    
    lastIndex => size - 1;
    
    rest => first == last then [] else next(first)..last;
    
    "This range in reverse, with [[first]] and [[last]]
     interchanged.
     
     For any two range endpoints, `x` and `y`: 
     
         `(x..y).reversed == y..x`
     
     except for [[recursive]] ranges, where the elements are
     evaluated and collected into a new sequence."
    //TODO: we should have a way to produce a decreasing
    //      recursive range
    shared actual 
    [Element+] reversed
            => recursive 
            then super.reversed
            else last..first;
    
    "The element of the range that occurs [[index]] values 
     after the start of the range."
    shared actual 
    Element? getFromFirst(Integer index) {
        if (index < 0) {
            return null;
        } else if (recursive) {
            return index < size then fromFirst(index);
        } else {
            value result = fromFirst(index);
            return !afterLast(result) then result;
        }
    }
    
    "An iterator for the elements of the range. The returned 
     iterator produces elements from [[first]] and continues 
     producing elements until it reaches an element whose 
     `offset` from [[last] is zero."
    shared actual 
    Iterator<Element> iterator() 
            => object
            satisfies Iterator<Element> {
        variable Boolean firstTime = true;
        variable Element|Finished element = first;
        shared actual Element|Finished next() {
            if (!is Finished c = element) {
                Element result;
                if (firstTime) {
                    firstTime = false;
                    result = c;
                } else {
                    result = outer.next(c);
                }
                if (result.offset(last) == 0) {
                    this.element = finished;
                } else {
                    this.element  = result;
                }
                return result;
            } else {
                return element ;
            }
        }
        string => "(``outer``).iterator()";
    };
    
    shared actual 
    {Element+} by(Integer step) {
        "step size must be greater than zero"
        assert (step > 0);
        return step == 1 then this else By(step);
    }
    
    shifted(Integer shift)
            => shift == 0
            then this
            else Span(first.neighbour(shift), 
                      last.neighbour(shift));
    
    containsElement(Element x)
{'fraction_non_alphanumeric': 0.08992426421244368, 'fraction_numerical': 0.004601668104687949, 'mean_word_length': 1.6935192357345727, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4417242', 'n_tokens_mistral': 2817, 'n_tokens_neox': 2645, 'n_words': 889}