package gui;
import builtin.math.Epsilon;
import builtin.system.ChangeString;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
*
* @author Oliver Chu
*/
public class SmartList<E> extends AbstractList<E> {
private ArrayList<E> list;
private Subprogram sub;
public boolean isRecursiveList;
public boolean isFrozen;
public boolean isInfinite() {
return sub != null || size() > 2100000000;
}
public boolean isAllIntegers() {
if (!isInfinite()) {
return false;
}
return get(0).toString().equals("0") &&
get(1).toString().equals("1") &&
get(2).toString().equals("-1") &&
get(3).toString().equals("2") &&
get(4).toString().equals("-2");
}
public boolean isAllPositiveIntegersAndZero() {
if (!isInfinite()) {
return false;
}
for (int j = 0, i = 129; j < 10; ++j, i += 2563) {
boolean cond = get(j).toString().equals("" + j);
boolean cond2 = get(i).toString().equals("" + i);
if (!(cond && cond2)) {
return false;
}
}
return true;
}
public SmartList() {
list = new ArrayList<E>();
sub = null;
isRecursiveList = false;
isFrozen = false;
}
public void freeze() {
isFrozen = true;
}
public void thaw() {
isFrozen = false;
}
public SmartList(Subprogram s) {
list = new ArrayList<E>();
sub = s;
}
public void changeToRecursiveList() {
isRecursiveList = true;
}
public void changeToRegularList() {
isRecursiveList = false;
isFrozen = false;
}
// Note: this doesn't do anything anymore.
private void checkBounds(int i) {
// Note: do not use i >= list.size() or else you will get random
// error messages that do not apply.
/* if (i < -list.size() || i > list.size()) {
System.err.println("List index out of bounds: Index " + i +
", List: " + list);
boolean choice = ShowQuestionBox.javaApply("Out of Bounds",
"You are attempting to evaluate: " + list + "[" + i + "]\n" +
"Normally this is out of bounds.\n\n" +
"Do you want to consider all lists to be circular?");
if (!choice) {
throw new MintException("OUT OF BOUNDS");
} else {
FileIO.strToFile("lists-are-circular", "lists-are-circular");
}
} */
}
public SmartList(E[] array) {
list = new ArrayList<E>();
list.addAll(Arrays.asList(array));
}
public SmartList(List<E> otherList) {
list = new ArrayList<E>();
list.addAll(otherList);
}
public SmartList(Collection<E> collection) {
list = new ArrayList<E>();
list.addAll(collection);
}
@Override
public E get(int i) {
if (isRecursiveList) {
int oldI = i;
while (oldI < 0) {
oldI += list.size();
}
oldI %= list.size();
i = Math.abs(i);
i &= 1;
if (i == 0) {
return list.get(0);
} else {
SmartList<E> cdr = new SmartList<E>();
for (int j = 1; j < list.size(); ++j) {
cdr.add(list.get(j));
}
if (!cdr.isEmpty()) {
cdr.changeToRecursiveList();
}
try {
// Return the cdr as a list.
return (E) Heap.allocateList((SmartList<Pointer>) cdr);
} catch (Throwable t) {
try {
// Return the cdr as a string.
return (E) Heap.allocateString(cdr.toString());
} catch (Throwable t2) {
try {
// This isn't cooperating, so just return
// the actual ith element.
return list.get(oldI);
} catch (Throwable t3) {
// This is ridiculous. We give up.
return null;
}
}
}
}
}
if (sub != null) {
SmartList<Pointer> args = new SmartList<Pointer>();
args.add(Heap.allocateInt(i));
try {
return (E) sub.execute(new Environment(),
new SmartList<String>(), args,
new Interpreter());
} catch (MintException ex) {
System.err.println(ex.getMessage());
}
}
/* try {
if (!FileIO.exists("lists-are-circular")) {
checkBounds(i);
}
} catch (Throwable t) {
System.err.println("" + t);
Mint.printStackTrace(t.getStackTrace());
} */
if (i < 0) {
i += list.size();
}
try {
if (list.isEmpty()) {
System.err.println("Error: List is empty!");
return null;
}
while (i < 0) {
i += list.size();
}
i %= list.size();
try {
return list.get(i);
} catch (Throwable t) {
return list.get(0);
}
} catch (Throwable t2) {}
return list.get(i);
}
@Override
public E set(int i, E value) {
if (isFrozen) {
try {
return (E) ChangeString.ERROR;
} catch (Throwable t) {
return null;
}
}
try {
if (!FileIO.exists("lists-are-circular")) {
checkBounds(i);
}
} catch (Throwable t) {
System.err.println("" + t);
Mint.printStackTrace(t.getStackTrace());
}
if (i < 0)
i += list.size();
return list.set(i, value);
}
public void prependAll(SmartList<E> lst) {
ArrayList<E> oldList = new ArrayList<E>();
for (int i = 0; i < list.size(); ++i) {
oldList.add(list.get(i));
}
list = new ArrayList<E>();
list.addAll(lst);
list.addAll(oldList);
}
@Override
public boolean add(E value) {
if (isFrozen) {
return false;
}
return list.add(value);
}
@Override
public void add(int i, E value) {
if (isFrozen) {
return;
}
list.add(i, value);
}
@Override
public boolean isEmpty() {
if (isRecursiveList) {
return false;
}
return list.isEmpty();
}
public SmartList<E> makeAllReals() {
sub = new Subprogram("epsilon",
new SmartList<Pointer>(new Pointer[]{Heap.allocateName("x")}),
new Epsilon());
return this;
}
@Override
public int size() {
if (isRecursiveList) {
return 2;
}
if (sub != null) {
// System.out.println("This list is actually infinitely long.");
return Integer.MAX_VALUE;
}
return list.size();
}
@Override
public boolean contains(Object value) {
return list.contains(value);
}
@Override
public E remove(int i) {
if (isFrozen) {
try {
return (E) ChangeString.ERROR;
} catch (Throwable t) {
return null;
}
}
return list.remove(i);
}
public SmartList<E> reverse() {
// If this list is frozen, then nothing happens!
if (isFrozen) {
return this;
}
ArrayList<E> oldList = list;
list = new ArrayList<E>();
for (int i = oldList.size() - 1; i >= 0; i--) {
list.add(oldList.get(i));
}
return this;
}
public int find(E e) {
int i = 0;
for (E item : list) {
if (item.equals(e))
return i;
i++;
}
return -1;
}
/** Removes the section of this list from index start to index end - 1,
* and replaces it with a new section 'sublist'.
*/
public void assignSublist(int start, int end, SmartList<E> sublist) {
if (isFrozen) {
return;
}
ArrayList<E> oldList = list;
list = new ArrayList<E>();
for (int i = 0; i < start; i++) {
list.add(oldList.get(i));
}
for (E element : sublist) {
list.add(element);
}
for (int i = end; i < oldList.size(); i++) {
list.add(oldList.get(i));
}
}
public void assignSublist(int start, int end, E value) {
if (isFrozen) {
return;
}
SmartList<E> sublist = new SmartList<E>();
sublist.add(value);
assignSublist(start, end, sublist);
}
public E pop() {
if (isFrozen) {
return list.get(list.size() - 1);
}
return list.remove(list.size() - 1);
}
public SmartList<E> subList(int start) {
return new SmartList<E>(subList(start, size()));
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
if (fromIndex < 0)
fromIndex += list.size();
if (toIndex < 0)
toIndex += list.size();
return list.subList(fromIndex, toIndex);
}
@Override
public String toString() {
int elementsLeft = list.size();
if (isRecursiveList) {
if (list.size() == 0) {
if (isFrozen) {
return "()";
}
return "[]";
} else if (list.size() == 1) {
if (isFrozen) {
return "(" + list.get(0) + " [])";
}
return "[" + list.get(0) + ", []]";
}
String result = "";
char counter;
for (counter = 'A'; counter <= 'Z' && elementsLeft > 0;
++counter, --elementsLeft) {
if (counter == 'A') {
if (isFrozen) {
result += "(" + list.get(counter - 'A') + ", " +
counter + ")\n";
} else {
result += "[" + list.get(counter - 'A') + ", " +
counter + "]\n";
}
} else {
if (isFrozen) {
result += (char) (counter - 1) +
" --> (" + list.get(counter - 'A') +
", " + counter + ")\n";
} else {
result += (char) (counter - 1) +
" --> [" + list.get(counter - 'A') +
", " + counter + "]\n";
}
}
}
--counter;
if (elementsLeft > 0) {
if (isFrozen) {
result += counter + " --> (...)";
} else {
result += counter + " --> [...]";
}
} else {
result += counter + " --> []";
}
return result;
}
if (sub != null) {
ArrayList<E> lst = new ArrayList<E>();
for (int i = 0; i < 10; i++) {
lst.add(get(i));
}
String x = lst.toString();
x = StrTools2.slice(x, 0, -1) + ", ...]";
return x;
}
if (isFrozen) {
String result = "(";
for (E e : list) {
result += e.toString() + " ";
}
return StrTools2.slice(result, 0, -1) + ")";
}
return list.toString();
}
}