namespace HeuristicLab.Problems.ProgramSynthesis {
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
///
/// While Push's Stacks are generally treated as genuine Stacks---that is, inclassions take their arguments from the
/// tops of
/// the Stacks and push their results onto the tops of the Stacks---a few inclassions (like YANK and SHOVE) do allow
/// direct access
/// to "deep" stack elements by means of integer indices. To this extent the Stacks can be used as general, random
/// access memory
/// classures. This is one of the features that ensures the Turing-completeness of Push (another being the arbitrary
/// name/value
/// bindings supported by the NAME data type and DEFINE methods; see below).
///
/// The item type of the collection.
public class PushStack : IPushStack {
private const string Delimiter = " ";
private readonly List data;
public PushStack(int capacity = 0) {
data = new List(capacity);
IsEnabled = true;
}
public bool IsEnabled { get; set; }
public int Capacity
{
get
{
return data.Capacity;
}
}
public T Top
{
get
{
return data[Count - 1];
}
set
{
data[Count - 1] = value;
}
}
public T TopOrDefault
{
get
{
return Count > 0 ? Top : default(T);
}
}
public T Bottom
{
get
{
return data[0];
}
}
public T BottomOrDefault
{
get
{
return Count > 0 ? Bottom : default(T);
}
}
public int Count
{
get
{
return data.Count;
}
}
public bool IsEmpty
{
get
{
return Count == 0;
}
}
public bool IsReadOnly
{
get
{
return false;
}
}
public void Add(T item) {
Push(item);
}
public void Clear() {
data.Clear();
}
public bool Contains(T item) {
return data.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex) {
data.CopyTo(array, arrayIndex);
}
public IEnumerator GetEnumerator() {
return data.GetEnumerator();
}
public T ElementAt(int index) {
return data[index];
}
public T this[int index]
{
get { return data[Count - 1 - index]; }
set { data[Count - 1 - index] = value; }
}
public void Swap(int count) {
var top = Top;
var bottomIndex = Count - count;
for (var i = Count - 1; i > bottomIndex; i--)
data[i] = data[i - 1];
data[bottomIndex] = top;
}
public void Yank(int index) {
if (index == Count - 1) return;
var item = data[index];
data.RemoveAt(index);
data.Add(item);
}
public T Pop() {
var top = Top;
data.RemoveAt(Count - 1);
return top;
}
public IReadOnlyList Pop(int count) {
var items = Peek(count);
Remove(count);
return items;
}
public IReadOnlyList Peek(int count) {
var startIndex = Count - count;
var items = new T[count];
data.CopyTo(startIndex, items, 0, count);
return items;
}
public void Push(T item) {
if (!IsEnabled) return;
data.Add(item);
}
public void Push(T item1, T item2) {
if (!IsEnabled) return;
data.Add(item1);
data.Add(item2);
}
public void Push(T item1, T item2, T item3) {
if (!IsEnabled) return;
data.Add(item1);
data.Add(item2);
data.Add(item3);
}
public void Push(T item1, T item2, T item3, T item4) {
if (!IsEnabled) return;
data.Add(item1);
data.Add(item2);
data.Add(item3);
data.Add(item4);
}
public void Push(IReadOnlyList items, int startIndex) {
if (!IsEnabled) return;
for (var i = startIndex; i < items.Count; i++) data.Add(items[i]);
}
public void Push(IReadOnlyList items) {
if (!IsEnabled) return;
data.AddRange(items);
}
public void Push(IEnumerable items) {
if (!IsEnabled) return;
data.AddRange(items);
}
public void Insert(int index, T item) {
if (!IsEnabled) return;
data.Insert(Count - index, item);
}
public bool Remove(T item) {
return data.Remove(item);
}
public void RemoveTop() {
data.RemoveAt(Count - 1);
}
public void Remove(int count) {
data.RemoveRange(Count - count, count);
}
public void RemoveAt(int index) {
data.RemoveAt(index);
}
public void RemoveAt(int index, int count) {
data.RemoveRange(index, count);
}
public bool TryPop(out T item) {
if (Count > 0) {
item = Pop();
return true;
}
item = default(T);
return false;
}
IEnumerator IEnumerable.GetEnumerator() {
return data.GetEnumerator();
}
public override string ToString() {
return string.Join(Delimiter, data.Select(x => x.ToString()).Reverse());
}
IEnumerable IPushStack.AsStrings() {
return data.Select(x => x.ToString());
}
IEnumerable