/* * 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; } }