Interval.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 java.util.List;
import java.util.ArrayList;
import Hoot.Magnitudes.Number;
import Hoot.Magnitudes.Integer;
import Hoot.Magnitudes.FastInteger;
import static Hoot.Magnitudes.SmallInteger.*;
import Smalltalk.Core.Subject;
import Smalltalk.Core.Classified;
import Smalltalk.Magnitudes.Ordinal;
import Smalltalk.Collections.Collected;
import Smalltalk.Collections.OrdinalRange;

public class Interval extends SequencedCollection implements OrdinalRange
{

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

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

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


    /**
     * @return 
     */
    @Override public   Interval $new()
    {
      java.lang.String exitID = "IntervalMetatype>>$new";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (Interval)f0.exit(exitID, this.from_to_by(Zero, Zero, Zero));
      });
    }

    /**
     * @return 
     */
    public   Interval from_to(final Ordinal start, final Ordinal stop)
    {
      java.lang.String exitID = "IntervalMetatype>>from_to";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (Interval)f0.exit(exitID, this.from_to_by(start, stop, (stop.minus(start)).sign()));
      });
    }

    /**
     * @return 
     */
    public   Interval from_to_by(final Ordinal start, final Ordinal stop, final Ordinal step)
    {
      java.lang.String exitID = "IntervalMetatype>>from_to_by";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (Interval)f0.exit(exitID, new Interval(start, stop, step));
      });
    }
  }


  protected Ordinal start = Zero;
  protected Ordinal stop = Zero;
  protected Ordinal step = Zero;
  protected static final String UnityForm = String.from("( %s to: %s )");
  protected static final String GeneralForm = String.from("( %s to: %s by: %s )");

  /**
   * 
   */
  protected    Interval(final Ordinal aStart, final Ordinal aStop, final Ordinal aStep)
  {
    java.lang.String exitID = "Interval>>Interval";
    Frame f0 = new Frame(exitID);
     start = aStart;

     stop = aStop;

     step = aStep;
  }

  /**
   * @return 
   */
  private   FastInteger fastStart()
  {
    java.lang.String exitID = "Interval>>fastStart";
    Frame f0 = new Frame(exitID);
    return (FastInteger)this.start().asSmallInteger().asFastInteger();
  }

  /**
   * @return 
   */
  private   SmallInteger smallStep()
  {
    java.lang.String exitID = "Interval>>smallStep";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)this.step().asSmallInteger();
  }

  /**
   * @return 
   */
  private   Integer start()
  {
    java.lang.String exitID = "Interval>>start";
    Frame f0 = new Frame(exitID);
    return (Integer)((Integer)start);
  }

  /**
   * @return 
   */
  private   Integer stop()
  {
    java.lang.String exitID = "Interval>>stop";
    Frame f0 = new Frame(exitID);
    return (Integer)((Integer)stop);
  }

  /**
   * @return 
   */
  private   Integer step()
  {
    java.lang.String exitID = "Interval>>step";
    Frame f0 = new Frame(exitID);
    return (Integer)((Integer)step);
  }

  /**
   * @return 
   */
  private   int startPrimly()
  {
    java.lang.String exitID = "Interval>>startPrimly";
    Frame f0 = new Frame(exitID);
    return (int)start.intValue();
  }

  /**
   * @return 
   */
  private   int stopPrimly()
  {
    java.lang.String exitID = "Interval>>stopPrimly";
    Frame f0 = new Frame(exitID);
    return (int)stop.intValue();
  }

  /**
   * @return 
   */
  private   int stepPrimly()
  {
    java.lang.String exitID = "Interval>>stepPrimly";
    Frame f0 = new Frame(exitID);
    return (int)step.intValue();
  }

  /**
   * @return 
   */
  private   int countSteps()
  {
    java.lang.String exitID = "Interval>>countSteps";
    Frame f0 = new Frame(exitID);
    return (int)(this.stopPrimly() - this.startPrimly() / this.stepPrimly() + 1);
  }

  /**
   * @return 
   */
  @Override public   Integer first()
  {
    java.lang.String exitID = "Interval>>first";
    Frame f0 = new Frame(exitID);
    this.emptyCheck();
    return (Integer)this.start();
  }

  /**
   * @return 
   */
  @Override public   Integer last()
  {
    java.lang.String exitID = "Interval>>last";
    Frame f0 = new Frame(exitID);
    this.emptyCheck();
    return (Integer)(this.stop().minus(this.stop().minus(this.start()).remainderFrom(step))).asInteger();
  }

  /**
   * @return 
   */
  @Override public   Integer size()
  {
    java.lang.String exitID = "Interval>>size";
    Frame f0 = new Frame(exitID);
    return (Integer)this._isEmpty().ifTrue_ifFalse(Closure.with(f2 -> {
      return Zero;
    }, ""), Closure.with(f2 -> {
      return SmallInteger.from(this.countSteps());
    }, ""));
  }

  /**
   * @return 
   */
  @Override public   Behavior species()
  {
    java.lang.String exitID = "Interval>>species";
    Frame f0 = new Frame(exitID);
    return (Behavior)((Behavior)OrderedCollection.type());
  }

  /**
   * @return 
   */
  @Override public   Boolean equals(final Collected aCollection)
  {
    java.lang.String exitID = "Interval>>equals";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    Interval.type().accepts(aCollection).ifFalse(Closure.with(f2 -> {
      return (Boolean)f0.exit(exitID, super.equals(aCollection));
    }, ""));

    Interval candidate = ((Interval)aCollection);
    return (Boolean)f0.exit(exitID, (candidate.start().equals(this.start())).and(Predicate.with(f2 -> {
      return (candidate.stop().equals(this.stop())).and(Predicate.with(f3 -> {
      return (candidate.step().equals(this.step()));
    }, ""));
    }, "")));
    });
  }

  /**
   * @return 
   */
  @Override public   int hashCode()
  {
    java.lang.String exitID = "Interval>>hashCode";
    Frame f0 = new Frame(exitID);
    int result = start.hashCode();
    result <<= 2;
    result ^= stop.hashCode();
    result <<= 1;
    result ^= step.hashCode();
    return (int)result;
  }

  /**
   * @return 
   */
  @Override protected   Integer get(final int index)
  {
    java.lang.String exitID = "Interval>>get";
    Frame f0 = new Frame(exitID);
    return (Integer)this.at((SmallInteger.from(index).plus(SmallInteger.from(1))));
  }

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

  /**
   * @return 
   */
  @Override public   Integer at_ifAbsent(final Ordinal index, final NiladicValuable aBlock)
  {
    java.lang.String exitID = "Interval>>at_ifAbsent";
    Frame f0 = new Frame(exitID);
    int i = this.checkIndex_ifAbsent(index, aBlock);
    i *= step.intValue();
    i += start.intValue();
    return (Integer)SmallInteger.from(i);
  }

  /**
   * @return 
   */
  private   String reportForm()
  {
    java.lang.String exitID = "Interval>>reportForm";
    Frame f0 = new Frame(exitID);
    return (String)(step.equals(SmallInteger.from(1))).ifTrue_ifFalse(Closure.with(f2 -> {
      return UnityForm;
    }, ""), Closure.with(f2 -> {
      return GeneralForm;
    }, ""));
  }

  /**
   * @return 
   */
  @Override public   String printString()
  {
    java.lang.String exitID = "Interval>>printString";
    Frame f0 = new Frame(exitID);
    return (String)this.reportForm().formatWith(((String)start.printString()), ((String)stop.printString()), ((String)step.printString()));
  }

  /**
   * @return 
   */
  @Override public   Interval reverse()
  {
    java.lang.String exitID = "Interval>>reverse";
    Frame f0 = new Frame(exitID);
    return (Interval)Interval.type().from_to_by(stop, start, step.negated().asInteger());
  }

  /**
   * @return 
   */
  @Override public   List<Ordinal> asList()
  {
    java.lang.String exitID = "Interval>>asList";
    Frame f0 = new Frame(exitID);
    List<Ordinal> results = new ArrayList();
    this.$do(Closure.with(f2 -> {
      Ordinal v = f2.getValue(0).value();
      results.add(v);
    }, "v"));
    return (List<Ordinal>)results;
  }

  /**
   * @return 
   */
  public   Closure testBlock(final FastInteger index)
  {
    java.lang.String exitID = "Interval>>testBlock";
    Frame f0 = new Frame(exitID);
    return (Closure)(Boolean.primitiveValue(this.stepsDown()) ? Closure.with(f3 -> {
      return stop.moreThan(index).not();
    }, "") : Closure.with(f3 -> {
      return index.moreThan(stop).not();
    }, ""));
  }

  /**
   * @return 
   */
  @Override public   Interval $do(final MonadicValuable aBlock)
  {
    java.lang.String exitID = "Interval>>$do";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    (step.equals(SmallInteger.from(0))).ifTrue(Closure.with(f2 -> {
      return (Interval)f0.exit(exitID, this);
    }, ""));

    FastInteger index = this.fastStart();
    this.testBlock(index).toPredicate().whileTrue(Closure.with(f2 -> {
      aBlock.value(index);
    index.add(this.smallStep());
    }, ""));
    return (Interval)this;
    });
  }

  /**
   * @return 
   */
  @Override public   OrderedCollection collect(final MonadicValuable filterBlock)
  {
    java.lang.String exitID = "Interval>>collect";
    Frame f0 = new Frame(exitID);
    FastInteger index = SmallInteger.from(0).asFastInteger();

    OrderedCollection result = OrderedCollection.type().$new(this.size());
    this.$do(Closure.with(f2 -> {
      Ordinal v = f2.getValue(0).value();
      index.add(SmallInteger.from(1));
    result.at_put(index, filterBlock.value(v));
    }, "v"));
    return (OrderedCollection)result;
  }

  /**
   * @return 
   */
  public   Boolean stepsDown()
  {
    java.lang.String exitID = "Interval>>stepsDown";
    Frame f0 = new Frame(exitID);
    return (Boolean)(step.lessThan(SmallInteger.from(0)));
  }

  /**
   * @return 
   */
  public   boolean stepsDownward()
  {
    java.lang.String exitID = "Interval>>stepsDownward";
    Frame f0 = new Frame(exitID);
    return (boolean)(step.intValue() < 0);
  }

  /**
   * @return 
   */
  @Override public   Boolean _isEmpty()
  {
    java.lang.String exitID = "Interval>>_isEmpty";
    Frame f0 = new Frame(exitID);
    return (Boolean)(SmallInteger.from(0).equals(step)).or(Predicate.with(f2 -> {
      return this.stepsDown().ifTrue_ifFalse(Closure.with(f3 -> {
      return (start.lessThan(stop));
    }, ""), Closure.with(f3 -> {
      return (stop.lessThan(start));
    }, ""));
    }, ""));
  }

  /**
   * @return 
   */
  @Override public   Boolean includes(final Subject aValue)
  {
    java.lang.String exitID = "Interval>>includes";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    Integer.type().accepts(aValue).ifFalse(Closure.with(f2 -> {
      return (Boolean)f0.exit(exitID, False.literal());
    }, ""));

    Integer candidate = ((Integer)aValue);
    return (Boolean)f0.exit(exitID, Boolean.from((candidate.lessThan(this.first())).or(Predicate.with(f2 -> {
      return (candidate.moreThan(this.last()));
    }, ""))).not());
    });
  }

  /**
   * @return 
   */
  public   Subject add(final Subject element)
  {
    java.lang.String exitID = "Interval>>add";
    Frame f0 = new Frame(exitID);
    this.immutabilityError();
    return (Subject)SmallInteger.from(0);
  }

  /**
   * @return 
   */
  protected   Object add_at(final Object element, final int index)
  {
    java.lang.String exitID = "Interval>>add_at";
    Frame f0 = new Frame(exitID);
    this.immutabilityError();
    return (Object)SmallInteger.from(0);
  }

  /**
   * @return 
   */
  public   Interval removeAll()
  {
    java.lang.String exitID = "Interval>>removeAll";
    Frame f0 = new Frame(exitID);
    this.immutabilityError();
    return (Interval)this;
  }

  /**
   * @return 
   */
  public   Subject removeFirst()
  {
    java.lang.String exitID = "Interval>>removeFirst";
    Frame f0 = new Frame(exitID);
    this.immutabilityError();
    return (Subject)SmallInteger.from(0);
  }

  /**
   * @return 
   */
  public   Subject removeLast()
  {
    java.lang.String exitID = "Interval>>removeLast";
    Frame f0 = new Frame(exitID);
    this.immutabilityError();
    return (Subject)SmallInteger.from(0);
  }

  /**
   * @return 
   */
  public   Subject removeAtIndex(final Ordinal index)
  {
    java.lang.String exitID = "Interval>>removeAtIndex";
    Frame f0 = new Frame(exitID);
    this.immutabilityError();
    return (Subject)SmallInteger.from(0);
  }
}