/*
* I don't like that this is in org.python.core, but PySequence has package
* private methods that I want to override. Hopefully we will clean up the
* PyList hierarchy in the future, and then maybe we will find a more sensible
* place for this class.
*/
package org.python.core;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.python.antlr.adapter.AstAdapter;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
import org.python.expose.MethodType;
@ExposedType(name = "_ast.astlist", base = PyList.class)
public class AstList extends PySequence implements Cloneable, List {
public static final PyType TYPE = PyType.fromClass(AstList.class);
private final static PyString[] fields = new PyString[0];
@ExposedGet(name = "_fields")
public PyString[] get_fields() { return fields; }
/** The underlying Java List. */
private List data;
private AstAdapter adapter;
public AstList() {
this(TYPE, new ArrayList(), null);
}
public AstList(List data) {
this(TYPE, data, null);
}
public AstList(List data, AstAdapter adapter) {
this(TYPE, data, adapter);
}
public AstList(PyType type, List data, AstAdapter adapter) {
super(TYPE);
if (data == null) {
data = new ArrayList();
}
this.data = data;
this.adapter = adapter;
}
@ExposedMethod(type = MethodType.BINARY)
final PyObject astlist___ne__(PyObject o) {
return seq___ne__(o);
}
@ExposedMethod(type = MethodType.BINARY)
final PyObject astlist___eq__(PyObject o) {
return seq___eq__(o);
}
@ExposedMethod(type = MethodType.BINARY)
final PyObject astlist___lt__(PyObject o) {
return seq___lt__(o);
}
@ExposedMethod(type = MethodType.BINARY)
final PyObject astlist___le__(PyObject o) {
return seq___le__(o);
}
@ExposedMethod(type = MethodType.BINARY)
final PyObject astlist___gt__(PyObject o) {
return seq___gt__(o);
}
@ExposedMethod(type = MethodType.BINARY)
final PyObject astlist___ge__(PyObject o) {
return seq___ge__(o);
}
@ExposedMethod
final boolean astlist___contains__(PyObject o) {
return object___contains__(o);
}
@ExposedMethod
final void astlist___delitem__(PyObject index) {
seq___delitem__(index);
}
@ExposedMethod
final void astlist___setitem__(PyObject o, PyObject def) {
seq___setitem__(o, def);
}
@ExposedMethod
final PyObject astlist___getitem__(PyObject o) {
PyObject ret = seq___finditem__(o);
if(ret == null) {
throw Py.IndexError("index out of range: " + o);
}
return ret;
}
@ExposedMethod
final boolean astlist___nonzero__() {
return seq___nonzero__();
}
@ExposedMethod
public PyObject astlist___iter__() {
return seq___iter__();
}
@ExposedMethod(defaults = "null")
final PyObject astlist___getslice__(PyObject start, PyObject stop, PyObject step) {
return seq___getslice__(start, stop, step);
}
@ExposedMethod(defaults = "null")
final void astlist___setslice__(PyObject start, PyObject stop, PyObject step, PyObject value) {
if(value == null) {
value = step;
step = null;
}
seq___setslice__(start, stop, step, value);
}
@ExposedMethod(defaults = "null")
final void astlist___delslice__(PyObject start, PyObject stop, PyObject step) {
seq___delslice__(start, stop, step);
}
public PyObject __imul__(PyObject o) {
return astlist___imul__(o);
}
@ExposedMethod(type = MethodType.BINARY)
final PyObject astlist___imul__(PyObject o) {
if (!o.isIndex()) {
return null;
}
int count = o.asIndex(Py.OverflowError);
int size = size();
if (size == 0 || count == 1) {
return this;
}
if (count < 1) {
clear();
return this;
}
if (size > Integer.MAX_VALUE / count) {
throw Py.MemoryError("");
}
int oldsize = data.size();
for (int i = 1; i < count; i++) {
data.addAll(data.subList(0, oldsize));
}
return this;
}
public PyObject __mul__(PyObject o) {
return astlist___mul__(o);
}
@ExposedMethod(type = MethodType.BINARY)
final PyObject astlist___mul__(PyObject o) {
if (!o.isIndex()) {
return null;
}
return repeat(o.asIndex(Py.OverflowError));
}
public PyObject __rmul__(PyObject o) {
return astlist___rmul__(o);
}
@ExposedMethod(type = MethodType.BINARY)
final PyObject astlist___rmul__(PyObject o) {
if (!o.isIndex()) {
return null;
}
return repeat(o.asIndex(Py.OverflowError));
}
public PyObject __iadd__(PyObject other) {
return astlist___iadd__(other);
}
@ExposedMethod
final PyObject astlist___iadd__(PyObject o) {
PyType oType = o.getType();
if (oType == TYPE || oType == PyTuple.TYPE || this == o) {
extend(fastSequence(o, "argument must be iterable"));
return this;
}
PyObject it;
try {
it = o.__iter__();
} catch (PyException pye) {
if (!pye.match(Py.TypeError)) {
throw pye;
}
return null;
}
extend(it);
return this;
}
public PyObject __add__(PyObject other) {
return astlist___add__(other);
}
@ExposedMethod(type = MethodType.BINARY)
final PyObject astlist___add__(PyObject o) {
AstList sum = null;
Object oList = o.__tojava__(List.class);
if(oList != Py.NoConversion && oList != null) {
List otherList = (List) oList;
sum = new AstList();
sum.extend(this);
for(Iterator i = otherList.iterator(); i.hasNext();) {
sum.add(i.next());
}
}
return sum;
}
public PyObject __radd__(PyObject o) {
return astlist___radd__(o);
}
@ExposedMethod(type = MethodType.BINARY)
final PyObject astlist___radd__(PyObject o) {
PyList sum = null;
Object oList = o.__tojava__(List.class);
if (oList != Py.NoConversion && oList != null) {
sum = new PyList();
sum.addAll((List) oList);
sum.extend(this);
}
return sum;
}
public int __len__() {
return data.size();
}
@Override
public String toString() {
return astlist_toString();
}
@ExposedMethod(names = "__repr__")
final String astlist_toString() {
return data.toString();
}
public void append(PyObject o) {
astlist_append(o);
}
@ExposedMethod
final void astlist_append(PyObject o) {
data.add(o);
}
public Object clone() {
return new AstList(this);
}
@ExposedMethod
final int astlist_count(PyObject value) {
int count = 0;
for(Object o : data) {
if(o.equals(value)) {
count++;
}
}
return count;
}
public int count(PyObject value) {
return astlist_count(value);
}
public int index(PyObject o) {
return astlist_index(o, 0, size());
}
public int index(PyObject o, int start) {
return astlist_index(o, start, size());
}
public int index(PyObject o, int start, int stop) {
return astlist_index(o, start, stop);
}
@ExposedMethod(defaults = {"null", "null"})
final int astlist_index(PyObject o, PyObject start, PyObject stop) {
int startInt = start == null ? 0 : PySlice.calculateSliceIndex(start);
int stopInt = stop == null ? size() : PySlice.calculateSliceIndex(stop);
return astlist_index(o, startInt, stopInt);
}
final int astlist_index(PyObject o, int start, int stop) {
return _index(o, "astlist.index(x): x not in list", start, stop);
}
final int astlist_index(PyObject o, int start) {
return _index(o, "astlist.index(x): x not in list", start, size());
}
final int astlist_index(PyObject o) {
return _index(o, "astlist.index(x): x not in list", 0, size());
}
private int _index(PyObject o, String message, int start, int stop) {
// Follow Python 2.3+ behavior
int validStop = boundToSequence(stop);
int validStart = boundToSequence(start);
for(int i = validStart; i < validStop && i < size(); i++) {
if(data.get(i).equals(o)) {
return i;
}
}
throw Py.ValueError(message);
}
protected void del(int i) {
data.remove(i);
}
protected void delRange(int start, int stop, int step) {
if(step >= 1) {
for(int i = start; i < stop; i += step) {
remove(i);
i--;
stop--;
}
} else if(step < 0) {
for(int i = start; i >= 0 && i >= stop; i += step) {
remove(i);
}
}
}
@ExposedMethod
final void astlist_extend(PyObject iterable){
int length = size();
setslice(length, length, 1, iterable);
}
public void extend(PyObject iterable) {
astlist_extend(iterable);
}
protected PyObject getslice(int start, int stop, int step) {
if(step > 0 && stop < start) {
stop = start;
}
int n = sliceLength(start, stop, step);
List newList = data.subList(start, stop);
if(step == 1) {
newList = data.subList(start, stop);
return new AstList(newList, adapter);
}
int j = 0;
for(int i = start; j < n; i += step) {
newList.set(j, data.get(i));
j++;
}
return new AstList(newList, adapter);
}
public void insert(int index, PyObject o) {
astlist_insert(index, o);
}
@ExposedMethod
final void astlist_insert(int index, PyObject o) {
if(index < 0) {
index = Math.max(0, size() + index);
}
if(index > size()) {
index = size();
}
data.add(index, o);
}
@ExposedMethod
final void astlist_remove(PyObject value){
del(_index(value, "astlist.remove(x): x not in list", 0, size()));
}
public void remove(PyObject value) {
astlist_remove(value);
}
public void reverse() {
astlist_reverse();
}
@ExposedMethod
final void astlist_reverse() {
Collections.reverse(data);
}
public PyObject pop() {
return pop(-1);
}
public PyObject pop(int n) {
return astlist_pop(n);
}
@ExposedMethod(defaults = "-1")
final PyObject astlist_pop(int n) {
if (adapter == null) {
return (PyObject)data.remove(n);
}
Object element = data.remove(n);
return adapter.ast2py(element);
}
protected PyObject repeat(int count) {
if (count < 0) {
count = 0;
}
int size = size();
int newSize = size * count;
if (count != 0 && newSize / count != size) {
throw Py.MemoryError("");
}
List newList = new ArrayList();
for(int i = 0; i < count; i++) {
newList.addAll(data);
}
return new AstList(newList);
}
protected void setslice(int start, int stop, int step, PyObject value) {
if(stop < start) {
stop = start;
}
if (value instanceof PySequence) {
PySequence sequence = (PySequence) value;
setslicePySequence(start, stop, step, sequence);
} else if (value instanceof List) {
List list = (List)value.__tojava__(List.class);
if(list != null && list != Py.NoConversion) {
setsliceList(start, stop, step, list);
}
} else {
setsliceIterable(start, stop, step, value);
}
}
protected void setslicePySequence(int start, int stop, int step, PySequence value) {
if (step != 0) {
if(value == this) {
PyList newseq = new PyList();
PyObject iter = value.__iter__();
for(PyObject item = null; (item = iter.__iternext__()) != null;) {
newseq.append(item);
}
value = newseq;
}
int n = value.__len__();
for (int i = 0, j = start; i < n; i++, j += step) {
pyset(j, value.pyget(i));
}
}
}
protected void setsliceList(int start, int stop, int step, List value) {
if(step != 1) {
throw Py.TypeError("setslice with java.util.List and step != 1 not supported yet");
}
int n = value.size();
for(int i = 0; i < n; i++) {
data.add(i + start, value.get(i));
}
}
protected void setsliceIterable(int start, int stop, int step, PyObject value) {
PyObject[] seq;
try {
seq = Py.make_array(value);
} catch (PyException pye) {
if (pye.match(Py.TypeError)) {
throw Py.TypeError("can only assign an iterable");
}
throw pye;
}
setslicePySequence(start, stop, step, new PyList(seq));
}
public void add(int index, Object element) {
data.add(index, element);
}
public boolean add(Object o) {
return data.add(o);
}
public boolean addAll(int index, Collection c) {
return data.addAll(index, c);
}
public boolean addAll(Collection c) {
return data.addAll(c);
}
public void clear() {
data.clear();
}
public boolean contains(Object o) {
return data.contains(o);
}
public boolean containsAll(Collection c) {
return data.containsAll(c);
}
public Object get(int index) {
return data.get(index);
}
public int indexOf(Object o) {
return data.indexOf(o);
}
public boolean isEmpty() {
return data.isEmpty();
}
public Iterator iterator() {
return data.iterator();
}
public int lastIndexOf(Object o) {
return data.lastIndexOf(o);
}
public ListIterator listIterator() {
return data.listIterator();
}
public ListIterator listIterator(int index) {
return data.listIterator(index);
}
public boolean pyadd(PyObject o) {
data.add(o);
return true;
}
public void pyadd(int index, PyObject element) {
data.add(index, element);
}
public PyObject pyget(int index) {
if (adapter == null) {
return (PyObject)data.get(index);
}
return adapter.ast2py(data.get(index));
}
public void pyset(int index, PyObject element) {
if (adapter == null) {
data.set(index, element);
} else {
Object o = adapter.py2ast(element);
data.set(index, o);
}
}
public Object remove(int index) {
return data.remove(index);
}
public boolean remove(Object o) {
return data.remove(o);
}
public boolean removeAll(Collection c) {
return data.removeAll(c);
}
public boolean retainAll(Collection c) {
return data.retainAll(c);
}
public Object set(int index, Object element) {
return data.set(index, element);
}
public int size() {
return data.size();
}
public List subList(int fromIndex, int toIndex) {
return data.subList(fromIndex, toIndex);
}
public Object[] toArray() {
return data.toArray();
}
public Object[] toArray(Object[] a) {
return data.toArray(a);
}
public Object __tojava__(Class c) {
if(c.isInstance(this)) {
return this;
}
return Py.NoConversion;
}
}