// Copyright (c) Corporation for National Research Initiatives package org.python.core; class SeqFuncs extends PyBuiltinFunctionSet { SeqFuncs(String name, int index, int argcount) { super(name, index, argcount, argcount, true, null); } public PyObject __call__() { PySequence seq = (PySequence)__self__; switch (index) { case 1: return new PyInteger(seq.__nonzero__() ? 1 : 0); default: throw argCountError(0); } } public PyObject __call__(PyObject arg) { PySequence seq = (PySequence)__self__; switch (index) { case 11: return seq.__getitem__(arg); case 12: seq.__delitem__(arg); return Py.None; case 13: return seq.__mul__(arg); case 14: return seq.__rmul__(arg); case 15: return new PyInteger(seq.__cmp__(arg)); default: throw argCountError(1); } } public PyObject __call__(PyObject arg1, PyObject arg2) { PySequence seq = (PySequence)__self__; switch (index) { case 21: seq.__setitem__(arg1, arg2); return Py.None; default: throw argCountError(1); } } public PyObject __call__(PyObject arg1, PyObject arg2, PyObject arg3) { PySequence seq = (PySequence)__self__; switch (index) { case 31: return seq.__getslice__(arg1, arg2, arg3); case 32: seq.__delslice__(arg1, arg2, arg3); return Py.None; default: throw argCountError(3); } } public PyObject __call__(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4) { PySequence seq = (PySequence)__self__; switch (index) { case 41: seq.__setslice__(arg1, arg2, arg3, arg4); return Py.None; default: throw argCountError(4); } } } /** * The abstract superclass of PyObjects that implements a Sequence. * Minimize the work in creating such objects. * * Method names are designed to make it possible for PySequence to * implement java.util.List interface when JDK 1.2 is ubiquitous. * * All subclasses must declare that they implement the ClassDictInit * interface, and provide an classDictInit() method that calls * PySequence.classDictInit(). * * Subclasses must also implement get, getslice, and repeat methods. * * Subclasses that are mutable should also implement: set, setslice, del, * and delRange. */ // this class doesn't "implement InitModule" because otherwise // PyJavaClass.init() would try to instantiate it. That fails because this // class is abstract. TBD: is there a way to test for whether a class is // abstract? abstract public class PySequence extends PyObject { /** * This constructor is used by PyJavaClass.init() */ public PySequence() {} /** * This constructor is used to pass on an __class__ attribute. */ public PySequence(PyClass c) { super(c); } /** Internal use only. Do not call this method explicit. */ public static void classDictInit(PyObject dict) { dict.__setitem__("__nonzero__", new SeqFuncs("__nonzero__", 1, 0)); dict.__setitem__("__getitem__", new SeqFuncs("__getitem__", 11, 1)); dict.__setitem__("__delitem__", new SeqFuncs("__delitem__", 12, 1)); dict.__setitem__("__mul__", new SeqFuncs("__mul__", 13, 1)); dict.__setitem__("__rmul__", new SeqFuncs("__rmul__", 14, 1)); dict.__setitem__("__cmp__", new SeqFuncs("__cmp__", 15, 1)); dict.__setitem__("__setitem__", new SeqFuncs("__setitem__", 21, 2)); dict.__setitem__("__getslice__", new SeqFuncs("__getslice__", 31, 3)); dict.__setitem__("__delslice__", new SeqFuncs("__delslice__", 32, 3)); dict.__setitem__("__setslice__", new SeqFuncs("__setslice__", 41, 4)); // TBD: __tojava__() // hide these from Python! dict.__setitem__("classDictInit", null); } // These methods must be defined for any sequence /** * @param index index of element to return. * @return the element at the given position in the list. */ abstract protected PyObject get(int index); /** * Returns a range of elements from the sequence. * * @param start the position of the first element. * @param stop one more than the position of the last element. * @param step the step size. * @return a sequence corresponding the the given range of elements. */ abstract protected PyObject getslice(int start, int stop, int step); /** * Repeats the given sequence. * * @param count the number of times to repeat the sequence. * @return this sequence repeated count times. */ abstract protected PyObject repeat(int count); // These methods only apply to mutable sequences /** * Sets the given element of the sequence. * * @param index index of the element to set. * @param value the value to set this element to. */ protected void set(int index, PyObject value) { throw Py.TypeError("can't assign to immutable object"); } /** * Sets the given range of elements. */ protected void setslice(int start, int stop, int step, PyObject value) { throw Py.TypeError("can't assign to immutable object"); } protected void del(int i) throws PyException { throw Py.TypeError("can't remove from immutable object"); } protected void delRange(int start, int stop, int step) { throw Py.TypeError("can't remove from immutable object"); } public boolean __nonzero__() { return __len__() != 0; } public PyObject __iter__() { return new PySequenceIter(this); } public synchronized PyObject __eq__(PyObject o) { if (o.__class__ != __class__) return null; int tl = __len__(); int ol = o.__len__(); if (tl != ol) return Py.Zero; int i = cmp(this, tl, o, ol); return (i < 0) ? Py.One : Py.Zero; } public synchronized PyObject __ne__(PyObject o) { if (o.__class__ != __class__) return null; int tl = __len__(); int ol = o.__len__(); if (tl != ol) return Py.One; int i = cmp(this, tl, o, ol); return (i < 0) ? Py.Zero : Py.One; } public synchronized PyObject __lt__(PyObject o) { if (o.__class__ != __class__) return null; int i = cmp(this, -1, o, -1); if (i < 0) return (i == -1) ? Py.One : Py.Zero; return __finditem__(i)._lt(o.__finditem__(i)); } public synchronized PyObject __le__(PyObject o) { if (o.__class__ != __class__) return null; int i = cmp(this, -1, o, -1); if (i < 0) return (i == -1 || i == -2) ? Py.One : Py.Zero; return __finditem__(i)._le(o.__finditem__(i)); } public synchronized PyObject __gt__(PyObject o) { if (o.__class__ != __class__) return null; int i = cmp(this, -1, o, -1); if (i < 0) return (i == -3) ? Py.One : Py.Zero; return __finditem__(i)._gt(o.__finditem__(i)); } public synchronized PyObject __ge__(PyObject o) { if (o.__class__ != __class__) return null; int i = cmp(this, -1, o, -1); if (i < 0) return (i == -3 || i == -2) ? Py.One : Py.Zero; return __finditem__(i)._ge(o.__finditem__(i)); } // Return value >= 0 is the index where the sequences differs. // -1: reached the end of o1 without a difference // -2: reached the end of both seqeunces without a difference // -3: reached the end of o2 without a difference private static int cmp(PyObject o1, int ol1, PyObject o2, int ol2) { if (ol1 < 0) ol1 = o1.__len__(); if (ol2 < 0) ol2 = o2.__len__(); int i = 0; for ( ; i < ol1 && i < ol2; i++) { if (!o1.__getitem__(i)._eq(o2.__getitem__(i)).__nonzero__()) return i; } if (ol1 == ol2) return -2; return (ol1 < ol2) ? -1 : -3; } // Return a copy of a sequence where the __len__() method is // telling the thruth. protected static PyObject fastSequence(PyObject seq, String msg) { if (seq instanceof PyList || seq instanceof PyTuple) return seq; if (!seq.isSequenceType()) throw Py.TypeError(msg); PyList list = new PyList(); PyObject iter = Py.iter(seq, msg); for (PyObject item = null; (item = iter.__iternext__()) != null; ) { list.append(item); } return list; } protected static final int sliceLength(int start, int stop, int step) { //System.err.println("slice: "+start+", "+stop+", "+step); int ret; if (step > 0) { ret = (stop-start+step-1)/step; } else { ret = (stop-start+step+1)/step; } if (ret < 0) return 0; return ret; } private static final int getIndex(PyObject index, int defaultValue) { if (index == Py.None || index == null) return defaultValue; if (index instanceof PyLong) { try { index = index.__int__(); } catch (PyException exc) { if (Py.matchException(exc, Py.OverflowError)) { if (new PyLong(0L).__cmp__(index) < 0) return Integer.MAX_VALUE; else return 0; } } } if (!(index instanceof PyInteger)) throw Py.TypeError("slice index must be int"); return ((PyInteger)index).getValue(); } protected int fixindex(int index) { int l = __len__(); if (index < 0) index += l; if (index < 0 || index >= l) return -1; //throw Py.IndexError("index out of range"); else return index; } public synchronized PyObject __finditem__(int index) { index = fixindex(index); if (index == -1) return null; else return get(index); } public PyObject __finditem__(PyObject index) { if (index instanceof PyInteger) return __finditem__(((PyInteger)index).getValue()); else if (index instanceof PySlice) { PySlice s = (PySlice)index; return __getslice__(s.start, s.stop, s.step); } else if (index instanceof PyLong) return __finditem__(index.__int__().getValue()); else throw Py.TypeError("sequence subscript must be integer or slice"); } public PyObject __getitem__(PyObject index) { PyObject ret = __finditem__(index); if (ret == null) { throw Py.IndexError("index out of range: "+index); } return ret; } public boolean isMappingType() { return false; } public boolean isNumberType() { return false; } protected static final int getStep(PyObject s_step) { int step = getIndex(s_step, 1); if (step == 0) { throw Py.TypeError("slice step of zero not allowed"); } return step; } protected static final int getStart(PyObject s_start, int step, int length) { int start; if (step < 0) { start = getIndex(s_start, length - 1); if (start < 0) start += length; if (start < 0) start = -1; if (start >= length) start = length - 1; } else { start = getIndex(s_start, 0); if (start < 0) start += length; if (start < 0) start = 0; if (start >= length) start = length; } return start; } protected static final int getStop(PyObject s_stop, int start, int step, int length) { int stop; if (step < 0) { stop = getIndex(s_stop, -1); if (stop < -1) stop = length+stop; if (stop < -1) stop = -1; } else { stop = getIndex(s_stop, length); if (stop < 0) stop = length+stop; if (stop < 0) stop = 0; } if (stop > length) stop = length; return stop; } public synchronized PyObject __getslice__(PyObject s_start, PyObject s_stop, PyObject s_step) { int length = __len__(); int step = getStep(s_step); int start = getStart(s_start, step, length); int stop = getStop(s_stop, start, step, length); return getslice(start, stop, step); } public synchronized void __setslice__(PyObject s_start, PyObject s_stop, PyObject s_step, PyObject value) { int length = __len__(); int step = getStep(s_step); int start = getStart(s_start, step, length); int stop = getStop(s_stop, start, step, length); setslice(start, stop, step, value); } public synchronized void __delslice__(PyObject s_start, PyObject s_stop, PyObject s_step) { int length = __len__(); int step = getStep(s_step); int start = getStart(s_start, step, length); int stop = getStop(s_stop, start, step, length); delRange(start, stop, step); } public synchronized void __setitem__(int index, PyObject value) { int i = fixindex(index); if (i == -1) throw Py.IndexError("index out of range: "+i); set(i, value); } public void __setitem__(PyObject index, PyObject value) { if (index instanceof PyInteger) __setitem__(((PyInteger)index).getValue(), value); else { if (index instanceof PySlice) { PySlice s = (PySlice)index; __setslice__(s.start, s.stop, s.step, value); } else if (index instanceof PyLong) { __setitem__(index.__int__().getValue(), value); } else { throw Py.TypeError( "sequence subscript must be integer or slice"); } } } public synchronized void __delitem__(PyObject index) { if (index instanceof PyInteger) { int i = fixindex(((PyInteger)index).getValue()); if (i == -1) throw Py.IndexError("index out of range: "+i); del(i); } else { if (index instanceof PySlice) { PySlice s = (PySlice)index; __delslice__(s.start, s.stop, s.step); } else if (index instanceof PyLong) { int i = fixindex(index.__int__().getValue()); if (i == -1) throw Py.IndexError("index out of range: "+i); del(i); } else { throw Py.TypeError( "sequence subscript must be integer or slice"); } } } public synchronized Object __tojava__(Class c) { if (c.isArray()) { Class component = c.getComponentType(); //System.out.println("getting: "+component); try { int n = __len__(); PyArray array = new PyArray(component, n); for (int i=0; i