SequencedCollection.java

/**
* Copyright 2010,2021 Nikolas S Boyd.
Permission is granted to copy this work provided this copyright statement is retained in all copies.

*/
package Hoot.Collections;

import Hoot.Runtime.Functions.*;
import Hoot.Runtime.Faces.*;
import Hoot.Runtime.Values.*;
import Hoot.Runtime.Blocks.*;
import Smalltalk.Core.*;
import Smalltalk.Blocks.*;
import Smalltalk.Magnitudes.*;
import Hoot.Behaviors.*;
import Hoot.Behaviors.Nil;
import Hoot.Behaviors.Object;
import Hoot.Behaviors.True;
import Hoot.Behaviors.False;
import Hoot.Behaviors.Boolean;
import Hoot.Magnitudes.*;
import Hoot.Magnitudes.Integer;
import Hoot.Magnitudes.Character;
import Hoot.Magnitudes.Float;
import Hoot.Magnitudes.Double;
import Hoot.Magnitudes.Number;
import Hoot.Magnitudes.Integer;
import static Hoot.Magnitudes.SmallInteger.*;
import Hoot.Streams.WriteStream;
import Hoot.Streams.ReadStream;
import Smalltalk.Blocks.*;
import Smalltalk.Collections.*;
import Smalltalk.Magnitudes.Ordinal;
import Smalltalk.Magnitudes.Numeric;
import Smalltalk.Core.Subject;

public abstract class SequencedCollection<ElementType extends Object> extends Collection<ElementType> implements CollectedOrdinally<ElementType>
{

  public static Metaclass type() { return (Metaclass)Metaclass.$class; }
  @Override public Metaclass $class() { return (Metaclass)Metaclass.$class; }
  public static class Metaclass extends Collection.Metaclass implements CollectedOrdinally.Metatype
  {
    static final SequencedCollection.Metaclass $class = new SequencedCollection.Metaclass();
    public Metaclass() {
      this(SequencedCollection.Metaclass.class);
    }

    public Metaclass(java.lang.Class aClass) {
      super(aClass);
    }

    @Override public java.lang.Class outerClass() { return SequencedCollection.class; }

  }



  /**
   * @return 
   */
  abstract protected   ElementType get(final int index);

  /**
   * @return 
   */
  abstract protected   ElementType add_at(final ElementType element, final int index);

  /**
   * @return 
   */
  public   ElementType first()
  {
    java.lang.String exitID = "SequencedCollection>>first";
    Frame f0 = new Frame(exitID);
    this.emptyCheck();
    return (ElementType)this.at(SmallInteger.from(1));
  }

  /**
   * @return 
   */
  public   ElementType last()
  {
    java.lang.String exitID = "SequencedCollection>>last";
    Frame f0 = new Frame(exitID);
    this.emptyCheck();
    return (ElementType)this.at(this.size());
  }

  /**
   * @return 
   */
  public   ElementType at(final Numeric index)
  {
    java.lang.String exitID = "SequencedCollection>>at";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.at(index.asInteger());
  }

  /**
   * @return 
   */
  public   ElementType at_ifAbsent(final Numeric index, final NiladicValuable noneBlock)
  {
    java.lang.String exitID = "SequencedCollection>>at_ifAbsent";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.at_ifAbsent(index.asInteger(), noneBlock);
  }

  /**
   * @return 
   */
  public   ElementType at(final Ordinal index)
  {
    java.lang.String exitID = "SequencedCollection>>at";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.at_ifAbsent(index, Closure.with(f2 -> {
      return this.indexRangeError();
    }, ""));
  }

  /**
   * @return 
   */
  public   ElementType at_ifAbsent(final Ordinal index, final NiladicValuable noneBlock)
  {
    java.lang.String exitID = "SequencedCollection>>at_ifAbsent";
    Frame f0 = new Frame(exitID);
    int i = this.checkIndex_ifAbsent(index, noneBlock);
    return (ElementType)this.get(i);
  }

  /**
   * @return 
   */
  public   Integer nextIndexOf_from_to(final ElementType element, final Integer start, final Integer stop)
  {
    java.lang.String exitID = "SequencedCollection>>nextIndexOf_from_to";
    Frame f0 = new Frame(exitID);
    return (Integer)this.nextIndexOf_from_to_ifAbsent(element, start, stop, Closure.with(f2 -> {
      return Negativity;
    }, ""));
  }

  /**
   * @return 
   */
  public   Integer nextIndexOf_from_to_ifAbsent(final ElementType element, final Integer start, final Integer stop, final NiladicValuable noneBlock)
  {
    java.lang.String exitID = "SequencedCollection>>nextIndexOf_from_to_ifAbsent";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    start.to_do(stop, Closure.with(f2 -> {
      Integer i = f2.getValue(0).value();
      return (Integer)f0.exit(exitID, (this.at(i).equals(element)).ifTrue(Closure.with(f3 -> {
      return (Integer)f0.exit(exitID, i);
    }, "")));
    }, "i"));
    return (Integer)f0.exit(exitID, noneBlock.value());
    });
  }

  /**
   * @return 
   */
  public   Integer prevIndexOf_from_to(final ElementType element, final Integer start, final Integer stop)
  {
    java.lang.String exitID = "SequencedCollection>>prevIndexOf_from_to";
    Frame f0 = new Frame(exitID);
    return (Integer)this.prevIndexOf_from_to_ifAbsent(element, start, stop, Closure.with(f2 -> {
      return Negativity;
    }, ""));
  }

  /**
   * @return 
   */
  public   Integer prevIndexOf_from_to_ifAbsent(final ElementType element, final Integer start, final Integer stop, final NiladicValuable noneBlock)
  {
    java.lang.String exitID = "SequencedCollection>>prevIndexOf_from_to_ifAbsent";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    start.to_by_do(stop, Negativity, Closure.with(f2 -> {
      Integer i = f2.getValue(0).value();
      return (Integer)f0.exit(exitID, (this.at(i).equals(element)).ifTrue(Closure.with(f3 -> {
      return (Integer)f0.exit(exitID, i);
    }, "")));
    }, "i"));
    return (Integer)f0.exit(exitID, noneBlock.value());
    });
  }

  /**
   * @return 
   */
  public   ElementType after(final ElementType leadingElement)
  {
    java.lang.String exitID = "SequencedCollection>>after";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    Integer index = this.nextIndexOf_from_to_ifAbsent(leadingElement, SmallInteger.from(1), this.size(), Closure.with(f2 -> {
      this.elementNotFound();
    return (ElementType)f0.exit(exitID, Zero);
    }, ""));
    return (ElementType)f0.exit(exitID, this.at((index.plus(SmallInteger.from(1))).asInteger()));
    });
  }

  /**
   * @return 
   */
  public   ElementType before(final ElementType trailingElement)
  {
    java.lang.String exitID = "SequencedCollection>>before";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    Integer index = this.prevIndexOf_from_to_ifAbsent(trailingElement, this.size(), SmallInteger.from(1), Closure.with(f2 -> {
      this.elementNotFound();
    return (ElementType)f0.exit(exitID, Zero);
    }, ""));
    return (ElementType)f0.exit(exitID, this.at((index.minus(SmallInteger.from(1))).asInteger()));
    });
  }

  /**
   * @return 
   */
  public   Integer indexOf(final ElementType element)
  {
    java.lang.String exitID = "SequencedCollection>>indexOf";
    Frame f0 = new Frame(exitID);
    return (Integer)this.indexOf_ifAbsent(element, Closure.with(f2 -> {
      return Zero;
    }, ""));
  }

  /**
   * @return 
   */
  public   Integer indexOf_ifAbsent(final ElementType element, final NiladicValuable noneBlock)
  {
    java.lang.String exitID = "SequencedCollection>>indexOf_ifAbsent";
    Frame f0 = new Frame(exitID);
    return (Integer)this.nextIndexOf_from_to_ifAbsent(element, SmallInteger.from(1), this.size(), noneBlock);
  }

  /**
   * @return 
   */
  public   Integer indexOfSubCollection_startingAt(final CollectedReadably<ElementType> subCollection, final Ordinal anIndex)
  {
    java.lang.String exitID = "SequencedCollection>>indexOfSubCollection_startingAt";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    Ordinal subSize = subCollection.size();

    FastInteger finalIndex = Zero.faster();
    (Zero.lessThan(subSize)).and(Predicate.with(f2 -> {
      return Zero.plus(this.size()).notLess(anIndex);
    }, "")).ifTrue(Closure.with(f2 -> {
      
    SequencedCollection sub = ((SequencedCollection)subCollection);

    Object firstSub = sub.at(Unity);

    Interval range = Unity.max(anIndex).to(Unity.plus(this.size()).minus(subSize));
    range.$do(Closure.with(f3 -> {
      Integer startIndex = f3.getValue(0).value();
      
    Object nextItem = this.at(startIndex);
    (nextItem.equals(firstSub)).ifTrue(Closure.with(f4 -> {
      
    FastInteger matchIndex = Duality.faster();
    Predicate.with(f5 -> {
      return (matchIndex.notMore(subSize)).and(Predicate.with(f6 -> {
      return (this.at(startIndex.plus(matchIndex).minus(SmallInteger.from(1))).equals(sub.at(matchIndex)));
    }, ""));
    }, "").whileTrue(Closure.with(f5 -> {
      matchIndex.increment();
    }, ""));
    return (Integer)f0.exit(exitID, (matchIndex.notMore(subSize)).ifFalse(Closure.with(f5 -> {
      finalIndex.value(startIndex);
    return (Integer)f0.exit(exitID, finalIndex.value());
    }, "")));
    }, ""));
    return (Integer)f0.exit(exitID, finalIndex.value());
    }, "startIndex"));
    }, ""));
    return (Integer)f0.exit(exitID, finalIndex.value());
    });
  }

  /**
   * @return 
   */
  public   Integer indexOfSubCollection_startingAt_ifAbsent(final CollectedReadably<ElementType> subCollection, final Ordinal anIndex, final NiladicValuable noneBlock)
  {
    java.lang.String exitID = "SequencedCollection>>indexOfSubCollection_startingAt_ifAbsent";
    Frame f0 = new Frame(exitID);
    Integer index = this.indexOfSubCollection_startingAt(subCollection, anIndex);
    return (Integer)(Boolean.primitiveValue((index.intValue() == Zero.intValue())) ? noneBlock.value() : index);
  }

  /**
   * @return 
   */
  public   SequencedCollection<ElementType> append(final CollectedReadably<ElementType> aCollection)
  {
    java.lang.String exitID = "SequencedCollection>>append";
    Frame f0 = new Frame(exitID);
    return (SequencedCollection<ElementType>)this.copyReplaceFrom_to_with((Unity.plus(this.size())), this.size(), aCollection);
  }

  /**
   * @return 
   */
  public   SequencedCollection<ElementType> copyRange(final Interval range)
  {
    java.lang.String exitID = "SequencedCollection>>copyRange";
    Frame f0 = new Frame(exitID);
    return (SequencedCollection<ElementType>)this.copyFrom_to(range.first(), range.last());
  }

  /**
   * @return 
   */
  public   SequencedCollection<ElementType> copyFrom_to(final Ordinal start, final Ordinal stop)
  {
    java.lang.String exitID = "SequencedCollection>>copyFrom_to";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    this._isEmpty().ifTrue(Closure.with(f2 -> {
      return (SequencedCollection<ElementType>)f0.exit(exitID, this.copy());
    }, ""));

    Integer newSize = (Unity.plus((stop.minus(start))));
    return (SequencedCollection<ElementType>)f0.exit(exitID, (fp) -> {
    SequencedCollection prime = (SequencedCollection)this.species().$new(newSize);
    prime.replaceFrom_to_with_startingAt(Unity, newSize, this, start); 

    return prime.yourself();
    });
    });
  }

  /**
   * @return 
   */
  public   SequencedCollection<ElementType> copyReplaceAll_with(final CollectedReadably<ElementType> oldElements, final CollectedReadably<ElementType> newElements)
  {
    java.lang.String exitID = "SequencedCollection>>copyReplaceAll_with";
    Frame f0 = new Frame(exitID);
    FastInteger oldIndex = Unity.faster();

    FastInteger matchIndex = this.indexOfSubCollection_startingAt(oldElements, oldIndex).faster();

    OrderedCollection<Integer> matchIndices = OrderedCollection.type().$new();
    Predicate.with(f2 -> {
      return (Zero.lessThan(matchIndex));
    }, "").whileTrue(Closure.with(f2 -> {
      matchIndices.addLast(matchIndex.value());
    matchIndex.add(oldElements.size());
    matchIndex.value(this.indexOfSubCollection_startingAt(oldElements, matchIndex.value()));
    }, ""));
    return (SequencedCollection<ElementType>)matchIndices._isEmpty().ifTrue_ifFalse(Closure.with(f2 -> {
      return this.copy();
    }, ""), Closure.with(f2 -> {
      
    FastInteger newIndex = Unity.faster();

    FastInteger newPlace = Zero.faster();

    Integer newSize = (this.size().plus(((newElements.size().minus(oldElements.size())).times(matchIndices.size())))).asInteger();

    OrderedCollection results = OrderedCollection.type().$new(newSize);
    results.registerType(oldElements.first());
    Predicate.with(f3 -> {
      return matchIndices._isEmpty();
    }, "").whileFalse(Closure.with(f3 -> {
      matchIndex.value(matchIndices.removeFirst());
    newPlace.value(newIndex.plus(matchIndex).minus(oldIndex));
    results.replaceFrom_to_with_startingAt(newIndex, (newPlace.plus(Negativity)), this, oldIndex);
    oldIndex.value((matchIndex.value().plus(oldElements.size())).asInteger());
    newIndex.value((newPlace.value().plus(newElements.size())).asInteger());
    return results.replaceFrom_to_with_startingAt(newPlace, (newIndex.plus(Negativity)), newElements, Unity);
    }, ""));
    results.replaceFrom_to_with_startingAt(newIndex.value(), results.size(), this, oldIndex.value());
    return results;
    }, ""));
  }

  /**
   * @return 
   */
  public   SequencedCollection<ElementType> copyReplaceFrom_to_with(final Ordinal start, final Ordinal stop, final CollectedReadably<ElementType> replacements)
  {
    java.lang.String exitID = "SequencedCollection>>copyReplaceFrom_to_with";
    Frame f0 = new Frame(exitID);
    Integer newSize = this.size().minus(Unity.plus(stop).minus(start)).plus(replacements.size()).asInteger();

    Integer end = SmallInteger.from(start.minus(Unity).plus(replacements.size()));
    {
    SequencedCollection prime = (SequencedCollection)this.species().$new(newSize);
    prime.replaceFrom_to_with_startingAt(Unity, (start.minus(Unity)).asInteger(), this, Unity); 
    prime.replaceFrom_to_with_startingAt(start, end, replacements, Unity); 
    prime.replaceFrom_to_with_startingAt((Unity.plus(end)), newSize, this, (Unity.plus(stop))); 

    return prime.yourself();
    }
  }

  /**
   * @return 
   */
  public   SequencedCollection<ElementType> copyReplaceFrom_to_withObject(final Ordinal start, final Ordinal stop, final ElementType replacement)
  {
    java.lang.String exitID = "SequencedCollection>>copyReplaceFrom_to_withObject";
    Frame f0 = new Frame(exitID);
    FastInteger size = (((Integer)stop).minus(start)).asSmallInteger().faster();
    (size.lessThan(SmallInteger.from(0))).ifTrue(Closure.with(f2 -> {
      return size.subtract(size);
    }, ""));
    size.add(Unity);

    Array replacements = Array.type().$new(size);
    replacements.atAllPut(replacement);
    return (SequencedCollection<ElementType>)this.copyReplaceFrom_to_with(start, stop, replacements);
  }

  /**
   * @return 
   */
  public   SequencedCollection<ElementType> copyWith(final ElementType newElement)
  {
    java.lang.String exitID = "SequencedCollection>>copyWith";
    Frame f0 = new Frame(exitID);
    Integer newSize = (Unity.plus(this.size()));
    {
    SequencedCollection prime = (SequencedCollection)this.species().$new(newSize);
    prime.at_put(newSize, newElement); 
    prime.replaceFrom_to_with_startingAt(Unity, this.size(), this, Unity); 

    return prime.yourself();
    }
  }

  /**
   * @return 
   */
  public   SequencedCollection<ElementType> copyWithout(final ElementType oldElement)
  {
    java.lang.String exitID = "SequencedCollection>>copyWithout";
    Frame f0 = new Frame(exitID);
    OrderedCollection copy = ((OrderedCollection)this.species().$new(this.size()).asOrderedCollection());

    WriteStream aStream = WriteStream.type().with(copy.registerType(oldElement));
    this.$do(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      return (oldElement.equals(element)).ifFalse(Closure.with(f3 -> {
      return aStream.nextPut(element);
    }, ""));
    }, "element"));
    return (SequencedCollection<ElementType>)((SequencedCollection)aStream.contents());
  }

  /**
   * @return 
   */
  public   SequencedCollection<ElementType> copyReplacing_withObject(final ElementType oldElement, final ElementType newElement)
  {
    java.lang.String exitID = "SequencedCollection>>copyReplacing_withObject";
    Frame f0 = new Frame(exitID);
    return (SequencedCollection<ElementType>)this.collect(Closure.with(f2 -> {
      ElementType each = f2.getValue(0).value();
      return (Boolean.primitiveValue(each.equals(oldElement)) ? newElement : each);
    }, "each"));
  }

  /**
   * @return 
   */
  public   SequencedCollection<ElementType> reverse()
  {
    java.lang.String exitID = "SequencedCollection>>reverse";
    Frame f0 = new Frame(exitID);
    OrderedCollection results = OrderedCollection.type().$new(this.size());
    this.reverseDo(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      return results.add(element);
    }, "element"));
    return (SequencedCollection<ElementType>)results;
  }

  /**
   * @return 
   */
  @Override public   SequencedCollection<ElementType> collect(final MonadicValuable filterBlock)
  {
    java.lang.String exitID = "SequencedCollection>>collect";
    Frame f0 = new Frame(exitID);
    OrderedCollection results = OrderedCollection.type().$new(this.size());
    Unity.to_do(this.size(), Closure.with(f2 -> {
      Integer index = f2.getValue(0).value();
      return results.at_put(index, ((Object)filterBlock.value(this.at(index))));
    }, "index"));
    return (SequencedCollection<ElementType>)results;
  }

  /**
   * @return 
   */
  @Override public   Integer findFirst(final MonadicPredicate testBlock)
  {
    java.lang.String exitID = "SequencedCollection>>findFirst";
    Frame f0 = new Frame(exitID);
    return (Integer)this.findFirst_ifAbsent(testBlock, Closure.with(f2 -> {
      return Zero;
    }, ""));
  }

  /**
   * @return 
   */
  @Override public   Integer findFirst_ifAbsent(final MonadicPredicate testBlock, final NiladicValuable noneBlock)
  {
    java.lang.String exitID = "SequencedCollection>>findFirst_ifAbsent";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    Unity.to_do(this.size(), Closure.with(f2 -> {
      Integer index = f2.getValue(0).value();
      return (Integer)f0.exit(exitID, testBlock.value(this.at(index)).ifTrue(Closure.with(f3 -> {
      return (Integer)f0.exit(exitID, index);
    }, "")));
    }, "index"));
    return (Integer)f0.exit(exitID, noneBlock.value());
    });
  }

  /**
   * @return 
   */
  @Override public   Integer findLast(final MonadicPredicate testBlock)
  {
    java.lang.String exitID = "SequencedCollection>>findLast";
    Frame f0 = new Frame(exitID);
    return (Integer)this.findLast_ifAbsent(testBlock, Closure.with(f2 -> {
      return Zero;
    }, ""));
  }

  /**
   * @return 
   */
  @Override public   Integer findLast_ifAbsent(final MonadicPredicate testBlock, final NiladicValuable noneBlock)
  {
    java.lang.String exitID = "SequencedCollection>>findLast_ifAbsent";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    this.size().to_by_do(Unity, Negativity, Closure.with(f2 -> {
      Integer index = f2.getValue(0).value();
      return (Integer)f0.exit(exitID, testBlock.value(this.at(index)).ifTrue(Closure.with(f3 -> {
      return (Integer)f0.exit(exitID, index);
    }, "")));
    }, "index"));
    return (Integer)f0.exit(exitID, noneBlock.value());
    });
  }

  /**
   * @return 
   */
  public   SequencedCollection from_to_do(final Ordinal start, final Ordinal stop, final MonadicValuable aBlock)
  {
    java.lang.String exitID = "SequencedCollection>>from_to_do";
    Frame f0 = new Frame(exitID);
    start.to_do(stop, Closure.with(f2 -> {
      Integer i = f2.getValue(0).value();
      return aBlock.value(this.at(i));
    }, "i"));
    return (SequencedCollection)this;
  }

  /**
   * @return 
   */
  public   SequencedCollection from_to_keysAndValuesDo(final Ordinal start, final Ordinal stop, final DyadicValuable aBlock)
  {
    java.lang.String exitID = "SequencedCollection>>from_to_keysAndValuesDo";
    Frame f0 = new Frame(exitID);
    start.to_do(stop, Closure.with(f2 -> {
      Integer i = f2.getValue(0).value();
      return aBlock.value_value(this.at(i), i);
    }, "i"));
    return (SequencedCollection)this;
  }

  /**
   * @return 
   */
  public   SequencedCollection keysAndValuesDo(final DyadicValuable aBlock)
  {
    java.lang.String exitID = "SequencedCollection>>keysAndValuesDo";
    Frame f0 = new Frame(exitID);
    this.from_to_keysAndValuesDo(Unity, this.size(), aBlock);
    return (SequencedCollection)this;
  }

  /**
   * @return 
   */
  @Override public   SequencedCollection $do(final MonadicValuable aBlock)
  {
    java.lang.String exitID = "SequencedCollection>>$do";
    Frame f0 = new Frame(exitID);
    Unity.to_do(this.size(), Closure.with(f2 -> {
      Integer i = f2.getValue(0).value();
      return aBlock.value(this.at(i));
    }, "i"));
    return (SequencedCollection)this;
  }

  /**
   * @return 
   */
  @Override public   SequencedCollection do_separatedBy(final MonadicValuable aBlock, final NiladicValuable separateBlock)
  {
    java.lang.String exitID = "SequencedCollection>>do_separatedBy";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    this._isEmpty().ifTrue(Closure.with(f2 -> {
      return (SequencedCollection)f0.exit(exitID, this);
    }, ""));
    aBlock.value(this.at(SmallInteger.from(1)));
    Duality.to_do(this.size(), Closure.with(f2 -> {
      Integer i = f2.getValue(0).value();
      separateBlock.value();
    return aBlock.value(this.at(i));
    }, "i"));
    return (SequencedCollection)this;
    });
  }

  /**
   * @return 
   */
  @Override public   SequencedCollection reverseDo(final MonadicValuable aBlock)
  {
    java.lang.String exitID = "SequencedCollection>>reverseDo";
    Frame f0 = new Frame(exitID);
    this.size().to_by_do(Unity, Negativity, Closure.with(f2 -> {
      Integer i = f2.getValue(0).value();
      return aBlock.value(this.at(i));
    }, "i"));
    return (SequencedCollection)this;
  }

  /**
   * @return 
   */
  public   SequencedCollection with_do(final CollectedReadably<ElementType> aCollection, final DyadicValuable aBlock)
  {
    java.lang.String exitID = "SequencedCollection>>with_do";
    Frame f0 = new Frame(exitID);
    (this.size().equals(aCollection.size())).ifFalse(Closure.with(f2 -> {
      this.error(String.from("Collections are of different sizes"));
    }, ""));
    Unity.to_do(this.size(), Closure.with(f2 -> {
      Integer index = f2.getValue(0).value();
      return aBlock.value_value(this.at(index), aCollection.at(index));
    }, "index"));
    return (SequencedCollection)this;
  }

  /**
   * @return 
   */
  public   ReadStream<ElementType> readStream()
  {
    java.lang.String exitID = "SequencedCollection>>readStream";
    Frame f0 = new Frame(exitID);
    return (ReadStream<ElementType>)ReadStream.type().on(this);
  }

  /**
   * @return 
   */
  @Override public   Boolean equals(final Collected<ElementType> aCollection)
  {
    java.lang.String exitID = "SequencedCollection>>equals";
    Frame f0 = new Frame(exitID);
    return (Boolean)SequencedCollection.type().accepts(aCollection).and(Predicate.with(f2 -> {
      return this.equals(((CollectedReadably)aCollection));
    }, ""));
  }

  /**
   * @return 
   */
  public   Boolean equals(final CollectedReadably<ElementType> aCollection)
  {
    java.lang.String exitID = "SequencedCollection>>equals";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    (this.size().equals(aCollection.size())).ifFalse(Closure.with(f2 -> {
      return (Boolean)f0.exit(exitID, False.literal());
    }, ""));
    this.with_do(aCollection, Closure.with(f2 -> {
      ElementType a = f2.getValue(0).value();
      ElementType b = f2.getValue(1).value();
      (a.equals(b)).ifFalse(Closure.with(f3 -> {
      return (Boolean)f0.exit(exitID, False.literal());
    }, ""));
    }, "a", "b"));
    return (Boolean)f0.exit(exitID, True.literal());
    });
  }

  /**
   * @return 
   */
  public   Boolean includesIndex(final Ordinal index)
  {
    java.lang.String exitID = "SequencedCollection>>includesIndex";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    (index.lessThan(Zero)).ifTrue(Closure.with(f2 -> {
      return (Boolean)f0.exit(exitID, False.literal());
    }, ""));
    return (Boolean)f0.exit(exitID, Boolean.from((index.lessThan(this.size()))));
    });
  }

  /**
   * @return 
   */
  public   ElementType atAllPut(final ElementType element)
  {
    java.lang.String exitID = "SequencedCollection>>atAllPut";
    Frame f0 = new Frame(exitID);
    return (ElementType)element;
  }

  /**
   * @return 
   */
  public   ElementType at_put(final Ordinal index, final ElementType element)
  {
    java.lang.String exitID = "SequencedCollection>>at_put";
    Frame f0 = new Frame(exitID);
    return (ElementType)element;
  }

  /**
   * @return 
   */
  public   ElementType atAll_put(final CollectedReadably<Ordinal> index, final ElementType element)
  {
    java.lang.String exitID = "SequencedCollection>>atAll_put";
    Frame f0 = new Frame(exitID);
    return (ElementType)element;
  }

  /**
   * @return 
   */
  protected   Interval replacedRange_from_at(final Interval range, final CollectedReadably<ElementType> replacements, final Integer origin)
  {
    java.lang.String exitID = "SequencedCollection>>replacedRange_from_at";
    Frame f0 = new Frame(exitID);
    if (!(this.isSame(replacements).primitiveBoolean())) {
      return range;
    };
    if (!((origin.intValue() < range.first().intValue()))) {
      return range;
    };
    return (Interval)range.reverse();
  }

  /**
   * @return 
   */
  public   SequencedCollection replaceFrom_to_with_startingAt(final Ordinal start, final Ordinal stop, final CollectedReadably<ElementType> replacements, final Ordinal origin)
  {
    java.lang.String exitID = "SequencedCollection>>replaceFrom_to_with_startingAt";
    Frame f0 = new Frame(exitID);
    Integer offset = (((Integer)origin).minus(((Integer)start)));

    Interval range = ((Integer)start).to_by(((Integer)stop), Unity);

     range = this.replacedRange_from_at(range, replacements, ((Integer)origin));
    range.$do(Closure.with(f2 -> {
      Integer i = f2.getValue(0).value();
      return this.at_put(i, replacements.at((i.plus(offset))));
    }, "i"));
    return (SequencedCollection)replacements;
  }

  /**
   * @return 
   */
  public   SequencedCollection replaceFrom_to_with(final Ordinal start, final Ordinal stop, final CollectedReadably<ElementType> replacements)
  {
    java.lang.String exitID = "SequencedCollection>>replaceFrom_to_with";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    (replacements.size().isSame(stop.minus(start).plus(SmallInteger.from(1)))).ifFalse(Closure.with(f2 -> {
      this.error(String.from("size of replacement incorrect"));
    return (SequencedCollection)f0.exit(exitID, replacements);
    }, ""));
    return (SequencedCollection)f0.exit(exitID, this.replaceFrom_to_with_startingAt(start, stop, replacements, Unity));
    });
  }

  /**
   * @return 
   */
  public   ElementType replaceFrom_to_withObject(final Ordinal start, final Ordinal stop, final ElementType element)
  {
    java.lang.String exitID = "SequencedCollection>>replaceFrom_to_withObject";
    Frame f0 = new Frame(exitID);
    Unity.to_do(this.size(), Closure.with(f2 -> {
      Integer index = f2.getValue(0).value();
      return this.at_put(index, element);
    }, "index"));
    return (ElementType)element;
  }

  /**
   * @return 
   */
  public   ElementType addFirst(final ElementType element)
  {
    java.lang.String exitID = "SequencedCollection>>addFirst";
    Frame f0 = new Frame(exitID);
    this.add_beforeIndex(element, Unity);
    return (ElementType)element;
  }

  /**
   * @return 
   */
  public   ElementType addLast(final ElementType element)
  {
    java.lang.String exitID = "SequencedCollection>>addLast";
    Frame f0 = new Frame(exitID);
    this.add(element);
    return (ElementType)element;
  }

  /**
   * @return 
   */
  public   Collected<ElementType> addAll(final Collected<ElementType> elements)
  {
    java.lang.String exitID = "SequencedCollection>>addAll";
    Frame f0 = new Frame(exitID);
    elements.$do(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      return this.add(element);
    }, "element"));
    return (Collected<ElementType>)elements;
  }

  /**
   * @return 
   */
  public   CollectedReadably<ElementType> addAllFirst(final CollectedReadably<ElementType> elements)
  {
    java.lang.String exitID = "SequencedCollection>>addAllFirst";
    Frame f0 = new Frame(exitID);
    elements.reverseDo(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      return this.addFirst(element);
    }, "element"));
    return (CollectedReadably<ElementType>)elements;
  }

  /**
   * @return 
   */
  public   CollectedReadably<ElementType> addAllLast(final CollectedReadably<ElementType> elements)
  {
    java.lang.String exitID = "SequencedCollection>>addAllLast";
    Frame f0 = new Frame(exitID);
    elements.$do(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      return this.addLast(element);
    }, "element"));
    return (CollectedReadably<ElementType>)elements;
  }

  /**
   * @return 
   */
  public   CollectedReadably<ElementType> addAll_after(final CollectedReadably<ElementType> elements, final ElementType target)
  {
    java.lang.String exitID = "SequencedCollection>>addAll_after";
    Frame f0 = new Frame(exitID);
    return (CollectedReadably<ElementType>)this.addAll_afterIndex(elements, this.indexOf_ifAbsent(target, Closure.with(f2 -> {
      this.elementNotFound();
    }, "")));
  }

  /**
   * @return 
   */
  public   CollectedReadably<ElementType> addAll_afterIndex(final CollectedReadably<ElementType> elements, final Ordinal index)
  {
    java.lang.String exitID = "SequencedCollection>>addAll_afterIndex";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    elements.inject_into(index, Closure.with(f2 -> {
      Ordinal i = f2.getValue(0).value();
      ElementType e = f2.getValue(1).value();
      this.add_afterIndex(e, i);
    return (CollectedReadably<ElementType>)f0.exit(exitID, (i.plus(Unity)));
    }, "i", "e"));
    return (CollectedReadably<ElementType>)f0.exit(exitID, elements);
    });
  }

  /**
   * @return 
   */
  public   CollectedReadably<ElementType> addAll_before(final CollectedReadably<ElementType> elements, final ElementType target)
  {
    java.lang.String exitID = "SequencedCollection>>addAll_before";
    Frame f0 = new Frame(exitID);
    return (CollectedReadably<ElementType>)this.addAll_beforeIndex(elements, this.indexOf_ifAbsent(target, Closure.with(f2 -> {
      return this.elementNotFound();
    }, "")));
  }

  /**
   * @return 
   */
  public   CollectedReadably<ElementType> addAll_beforeIndex(final CollectedReadably<ElementType> elements, final Ordinal index)
  {
    java.lang.String exitID = "SequencedCollection>>addAll_beforeIndex";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    elements.inject_into(index, Closure.with(f2 -> {
      Ordinal i = f2.getValue(0).value();
      ElementType e = f2.getValue(1).value();
      this.add_beforeIndex(e, i);
    return (CollectedReadably<ElementType>)f0.exit(exitID, (i.plus(Unity)));
    }, "i", "e"));
    return (CollectedReadably<ElementType>)f0.exit(exitID, elements);
    });
  }

  /**
   * @return 
   */
  public   ElementType add_after(final ElementType element, final ElementType target)
  {
    java.lang.String exitID = "SequencedCollection>>add_after";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.add_afterIndex(element, this.indexOf_ifAbsent(target, Closure.with(f2 -> {
      this.elementNotFound();
    return Nil.literal();
    }, "")));
  }

  /**
   * @return 
   */
  public   ElementType add_afterIndex(final ElementType element, final Ordinal index)
  {
    java.lang.String exitID = "SequencedCollection>>add_afterIndex";
    Frame f0 = new Frame(exitID);
    int i = this.checkRange((Unity.plus(index)));
    this.registerType(((Object)element));
    this.add_at(element, i);
    return (ElementType)element;
  }

  /**
   * @return 
   */
  public   ElementType add_before(final ElementType element, final ElementType target)
  {
    java.lang.String exitID = "SequencedCollection>>add_before";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.add_beforeIndex(element, this.indexOf_ifAbsent(target, Closure.with(f2 -> {
      this.elementNotFound();
    return Nil.literal();
    }, "")));
  }

  /**
   * @return 
   */
  public   ElementType add_beforeIndex(final ElementType element, final Ordinal index)
  {
    java.lang.String exitID = "SequencedCollection>>add_beforeIndex";
    Frame f0 = new Frame(exitID);
    int i = this.checkRange(index);
    this.registerType(((Object)element));
    this.add_at(element, i);
    return (ElementType)element;
  }

  /**
   * @return 
   */
  public   Collected<ElementType> removeAll(final Collected<ElementType> elements)
  {
    java.lang.String exitID = "SequencedCollection>>removeAll";
    Frame f0 = new Frame(exitID);
    elements.$do(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      return this.remove(element);
    }, "element"));
    return (Collected<ElementType>)elements;
  }

  /**
   * @return 
   */
  public   ElementType remove(final ElementType element)
  {
    java.lang.String exitID = "SequencedCollection>>remove";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.remove_ifAbsent(element, Closure.with(f2 -> {
      this.elementNotFound();
    return Nil.literal();
    }, ""));
  }

  /**
   * @return 
   */
  public   ElementType remove_ifAbsent(final ElementType element, final NiladicValuable aBlock)
  {
    java.lang.String exitID = "SequencedCollection>>remove_ifAbsent";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.removeAtIndex(this.indexOf_ifAbsent(element, aBlock));
  }

  /**
   * @return 
   */
  public   OrderedCollection<ElementType> removeAllSuchThat(final MonadicPredicate criteria)
  {
    java.lang.String exitID = "SequencedCollection>>removeAllSuchThat";
    Frame f0 = new Frame(exitID);
    OrderedCollection<ElementType> results = OrderedCollection.type().$new();
    this.$do(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      return criteria.value(element).ifTrue(Closure.with(f3 -> {
      results.add(element);
    this.remove(element);
    }, ""));
    }, "element"));
    return (OrderedCollection<ElementType>)results;
  }
}