package st.gravel.support.jvm;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import st.gravel.support.compiler.ast.SimpleTraitUsageNode;
import st.gravel.support.compiler.jvm.JVMType;
public class ArrayExtensions {
public static <E> boolean allSatisfy_(E[] receiver, Predicate1<E> predicate) {
for (E element : receiver) {
if (!predicate.value_(element))
return false;
}
return true;
}
public static <E> boolean anySatisfy_(E[] receiver, Predicate1<E> predicate) {
for (E element : receiver) {
if (predicate.value_(element))
return true;
}
return false;
}
public static <E> E[] asSortedArray(E[] receiver) {
E[] arr = receiver.clone();
Arrays.sort(arr);
return arr;
}
public static <E> E at_(E[] receiver, int index) {
return receiver[index - 1];
}
public static <E> E at_put_(E[] receiver, int index, E value) {
return receiver[index - 1] = value;
}
public static <R, E> R[] collect_(E[] receiver, Block1<R, E> aBlock) {
R[] result = (R[]) Array.newInstance(aBlock.getResultClass(),
receiver.length);
for (int i = 0; i < receiver.length; i++) {
result[i] = aBlock.value_(receiver[i]);
}
return result;
}
public static <E> E[] copy(E[] receiver) {
return receiver.clone();
}
public static <E> E[] copyAt_put_(E[] receiver, int index, E value) {
E[] arr = Arrays.copyOf(receiver, receiver.length);
arr[index - 1] = value;
return arr;
}
public static <E> E[] copyWith_(E[] receiver, E element) {
final Class<? extends Object> class1 = receiver.getClass()
.getComponentType();
if (element != null) {
final Class<? extends Object> class2 = element.getClass();
if (class1 != class2) {
Class<?> commonSuperclass = ArrayFactory.commonSuperclass(
class1, class2);
E[] newInstance = (E[]) Array.newInstance(commonSuperclass,
receiver.length + 1);
System.arraycopy(receiver, 0, newInstance, 0, receiver.length);
newInstance[receiver.length] = element;
return newInstance;
}
}
final int N = receiver.length;
E[] arr = Arrays.copyOf(receiver, N + 1);
arr[N] = element;
return arr;
}
public static <E> E[] copyWithAll_(E[] receiver, E[] other) {
final int rLen = receiver.length;
E[] copy = Arrays.copyOf(receiver, rLen + other.length);
System.arraycopy(other, 0, copy, rLen, other.length);
return copy;
}
public static <E> E[] copyWithFirst_(E[] receiver, E element) {
final int N = receiver.length;
int newLength = N + 1;
Class newType = receiver.getClass();
E[] copy = (newType == Object[].class) ? (E[]) new Object[newLength]
: (E[]) Array
.newInstance(newType.getComponentType(), newLength);
System.arraycopy(receiver, 0, copy, 1, receiver.length);
copy[0] = element;
return copy;
}
public static <E> E[] copyWithoutLast(E[] receiver) {
final int N = receiver.length;
E[] arr = Arrays.copyOf(receiver, N - 1);
return arr;
}
public static <E> E detect_ifNone_(E[] receiver, Predicate1<E> predicate,
Block0<E> failBlock) {
for (E elem : receiver) {
if (predicate.value_(elem))
return elem;
}
return failBlock.value();
}
public static <E> Object do_(E[] receiver, Object aBlock) {
Block1 bl = (Block1) aBlock;
for (Object element : receiver) {
bl.value_(element);
}
return receiver;
}
public static boolean equals_(Object[] receiver, Object[] other) {
return (receiver == null && other == null)
|| (receiver != null && other != null && (isSameAs_(receiver,
other)));
}
public static boolean includes_(char[] receiver, Character element) {
if (element == null)
return false;
for (char ch : receiver) {
if (ch == element)
return true;
}
return false;
}
public static <E> boolean includes_(E[] receiver, E element) {
for (E elem : receiver) {
if (elem.equals(element))
return true;
}
return false;
}
public static <E> int indexOf_(E[] receiver, E element) {
for (int i = 0; i < receiver.length; i++) {
if (receiver[i].equals(element))
return i + 1;
}
return 0;
}
public static <E> int indexWhere_(E[] receiver, Predicate1<E> predicate) {
for (int i = 0; i < receiver.length; i++) {
if (predicate.value_(receiver[i]))
return i + 1;
}
return 0;
}
public static <S, E> S inject_into_(E[] receiver, S startSum,
Block2<S, S, E> block2) {
S sum = startSum;
for (E elem : receiver) {
sum = block2.value_value_(sum, elem);
}
return sum;
}
public static <Object> boolean isSameAs_(Object[] receiver, Object[] other) {
if (receiver == other)
return true;
if (receiver.length != other.length)
return false;
for (int i = 0; i < receiver.length; i++) {
Object a = receiver[i];
Object b = other[i];
if (!((a == null && b == null) | (a != null && b != null && a
.equals(b))))
return false;
}
return true;
}
public static <E> String join_(E[] receiver, Block1<String, E> block) {
return join_with_(receiver, block, "");
}
public static <E> String join_with_(E[] receiver, Block1<String, E> block,
String sepString) {
StringBuilder str = new StringBuilder();
for (int i = 0; i < receiver.length; i++) {
if (i != 0)
str.append(sepString);
E element = receiver[i];
str.append(block.value_(element));
}
return str.toString();
}
public static String joinWith_(String[] receiver, String separator) {
StringBuilder str = new StringBuilder();
for (int i = 0; i < receiver.length; i++) {
if (i != 0) {
str.append(separator);
}
str.append(receiver[i]);
}
return str.toString();
}
public static <R, E> R[] keysAndValuesCollect_(E[] receiver,
Block2<R, Integer, E> aBlock) {
R[] result = (R[]) Array.newInstance(aBlock.getResultClass(),
receiver.length);
for (int i = 0; i < receiver.length; i++) {
result[i] = aBlock.value_value_(i + 1, receiver[i]);
}
return result;
}
public static Object[] newInstance_(Object receiverClass, int size) {
return new Object[size];
}
public static <E> E[] reject_(E[] receiver, Predicate1<E> predicate) {
ArrayList<E> list = new ArrayList<E>();
for (E elem : receiver) {
if (!predicate.value_(elem)) {
list.add(elem);
}
}
E[] newInstance = (E[]) Array.newInstance(receiver.getClass()
.getComponentType(), list.size());
return list.toArray(newInstance);
}
public static Object[] replaceFrom_to_with_startingAt_(Object[] receiver,
int start, int stop, Object[] replacement, int repStart) {
// Primitive. This destructively replaces elements from start to stop in
// the receiver starting at index, repStart, in the collection,
// replacement. Answer the receiver. Range checks are performed in the
// primitive only. Optional. See Object documentation whatIsAPrimitive.
int length = (stop - start) + 1;
System.arraycopy(replacement, repStart - 1, receiver, start - 1, length);
return receiver;
}
public static <E> E[] reverse(E[] receiver) {
E[] result = receiver.clone();
int length = receiver.length;
for (int i = 0; i < length; i++) {
result[i] = receiver[(length - i) - 1];
}
return result;
}
public static <E> E[] select_(E[] receiver, Predicate1<E> predicate) {
ArrayList<E> list = new ArrayList<E>();
for (E elem : receiver) {
if (predicate.value_(elem)) {
list.add(elem);
}
}
E[] newInstance = (E[]) Array.newInstance(receiver.getClass()
.getComponentType(), list.size());
return list.toArray(newInstance);
}
public static <E> E[] shallowCopy(E[] receiver) {
return receiver.clone();
}
public static <E> Object size(E[] receiver) {
return receiver.length;
}
public static <O, N> void syncWith(O[] receiver, N[] newCollection,
Predicate2<O, N> selectBlock, Block2<Object, O, N> thenBlock,
Block1<Object, N> ifNewBlock, Block1<Object, O> ifAbsentBlock) {
final HashSet<O> oldElems = new HashSet<O>(Arrays.asList(receiver));
final HashSet<N> newElems = new HashSet<N>(Arrays.asList(newCollection));
for (O o : oldElems) {
boolean notFound = true;
for (N n : newElems) {
if (selectBlock.value_value_(o, n)) {
newElems.remove(n);
thenBlock.value_value_(o, n);
notFound = false;
break;
}
}
if (notFound) {
ifAbsentBlock.value_(o);
}
}
for (N n : newElems) {
ifNewBlock.value_(n);
}
}
public static <E> E[] tail(E[] receiver) {
final int N = receiver.length;
int newLength = N - 1;
Class newType = receiver.getClass();
E[] copy = (newType == Object[].class) ? (E[]) new Object[newLength]
: (E[]) Array
.newInstance(newType.getComponentType(), newLength);
System.arraycopy(receiver, 0, copy, 0, newLength);
return copy;
}
public static <X, Y> Object with_do_(X[] receiver, Y[] other,
Block2<Object, X, Y> doBlock) {
if (receiver.length != other.length)
throw new RuntimeException("Arrays are not of same length");
for (int i = 0; i < receiver.length; i++) {
X a = receiver[i];
Y b = other[i];
doBlock.value_value_(a, b);
}
return receiver;
}
public static <X, Y> Object with_do_separatedBy_(X[] receiver, Y[] other,
Block2<Object, X, Y> doBlock, Block0<Object> sepBlock) {
if (receiver.length != other.length)
throw new RuntimeException("Arrays are not of same length");
for (int i = 0; i < receiver.length; i++) {
X a = receiver[i];
Y b = other[i];
if (i != 0) {
sepBlock.value();
}
doBlock.value_value_(a, b);
}
return receiver;
}
public static <E> E zeroAt_(E[] receiver, int index) {
return receiver[index];
}
public static <E> E zeroAt_put_(E[] receiver, int index, E value) {
return receiver[index] = value;
}
}