source: branches/0.17.x/abcl/src/org/armedbear/lisp/AbstractArray.java

Last change on this file was 12254, checked in by ehuelsmann, 16 years ago

Remove 'throws ConditionThrowable?' method annotations:

it's an unchecked exception now, so no need to declare it thrown.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 11.3 KB
Line 
1/*
2 * AbstractArray.java
3 *
4 * Copyright (C) 2003-2005 Peter Graves
5 * $Id: AbstractArray.java 12254 2009-11-06 20:07:54Z ehuelsmann $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36public abstract class AbstractArray extends LispObject
37{
38    @Override
39    public LispObject typep(LispObject type)
40    {
41        if (type == Symbol.ARRAY)
42            return T;
43        if (type == BuiltInClass.ARRAY)
44            return T;
45        return super.typep(type);
46    }
47
48    @Override
49    public boolean equalp(LispObject obj)
50    {
51        if (obj instanceof AbstractArray) {
52            AbstractArray a = (AbstractArray) obj;
53            if (getRank() != a.getRank())
54                return false;
55            for (int i = getRank(); i-- > 0;) {
56                if (getDimension(i) != a.getDimension(i))
57                    return false;
58            }
59            for (int i = getTotalSize(); i--> 0;) {
60                if (!AREF(i).equalp(a.AREF(i)))
61                    return false;
62            }
63            return true;
64        }
65        return false;
66    }
67
68    public boolean isDisplaced()
69    {
70        return false;
71    }
72
73    public LispObject arrayDisplacement()
74    {
75        return LispThread.currentThread().setValues(NIL, Fixnum.ZERO);
76    }
77
78    public boolean hasFillPointer()
79    {
80        return false;
81    }
82
83    public int getFillPointer()
84    {
85        noFillPointer();
86        return -1; // Not reached.
87    }
88
89    public void setFillPointer(LispObject fillPointer)
90    {
91        setFillPointer(fillPointer.intValue());
92    }
93
94    public void setFillPointer(int fillPointer)
95    {
96        noFillPointer();
97    }
98
99    public boolean isAdjustable()
100    {
101        return true;
102    }
103
104    public abstract int getRank();
105
106    public abstract LispObject getDimensions();
107
108    public abstract int getDimension(int n);
109
110    public abstract LispObject getElementType();
111
112    public abstract int getTotalSize();
113
114    @Override
115    public abstract void aset(int index, LispObject newValue)
116       ;
117
118    // FIXME Detect overflow!
119    protected static final int computeTotalSize(int[] dimensions)
120    {
121        int size = 1;
122        for (int i = dimensions.length; i-- > 0;)
123            size *= dimensions[i];
124        return size;
125    }
126
127    public int getRowMajorIndex(LispObject[] subscripts)
128
129    {
130        int[] subs = new int[subscripts.length];
131        for (int i = 0; i < subscripts.length; i++) {
132            LispObject subscript = subscripts[i];
133            if (subscript instanceof Fixnum)
134                subs[i] = ((Fixnum)subscript).value;
135            else
136                type_error(subscript, Symbol.FIXNUM);
137        }
138        return getRowMajorIndex(subs);
139    }
140
141    public int getRowMajorIndex(int[] subscripts)
142    {
143        final int rank = getRank();
144        if (rank != subscripts.length) {
145            // ### i18n
146            final String errorMsg =
147                "Wrong number of subscripts (%d) for array of rank %d.";
148            error(new ProgramError(String.format(errorMsg, subscripts.length, rank)));
149        }
150        int sum = 0;
151        int size = 1;
152        for (int i = rank; i-- > 0;) {
153            final int dim = getDimension(i);
154            final int lastSize = size;
155            size *= dim;
156            final int n = subscripts[i];
157            if (n < 0 || n >= dim) {
158                // ### i18n
159                final String errorMsg =
160                    "Invalid index %d for array %s.";
161                error(new ProgramError(String.format(errorMsg, n, writeToString())));
162            }
163            sum += n * lastSize;
164        }
165        return sum;
166    }
167
168    public LispObject get(int[] subscripts)
169    {
170        return AREF(getRowMajorIndex(subscripts));
171    }
172
173    public void set(int[] subscripts, LispObject newValue)
174
175    {
176        aset(getRowMajorIndex(subscripts), newValue);
177    }
178
179    public abstract void fill(LispObject obj);
180
181    public String writeToString(int[] dimv)
182    {
183        StringBuilder sb = new StringBuilder();
184        LispThread thread = LispThread.currentThread();
185        LispObject printReadably = Symbol.PRINT_READABLY.symbolValue(thread);
186        if (printReadably != NIL || Symbol.PRINT_ARRAY.symbolValue(thread) != NIL) {
187            int maxLevel = Integer.MAX_VALUE;
188            if (printReadably != NIL) {
189                for (int i = 0; i < dimv.length - 1; i++) {
190                    if (dimv[i] == 0) {
191                        for (int j = i + 1; j < dimv.length; j++) {
192                            if (dimv[j] != 0) {
193                                error(new PrintNotReadable(list(Keyword.OBJECT,
194                                                                  this)));
195                                return null; // Not reached.
196                            }
197                        }
198                    }
199                }
200            } else {
201                LispObject printLevel = Symbol.PRINT_LEVEL.symbolValue(thread);
202                if (printLevel instanceof Fixnum)
203                    maxLevel = ((Fixnum)printLevel).value;
204            }
205            LispObject currentPrintLevel =
206                _CURRENT_PRINT_LEVEL_.symbolValue(thread);
207            int currentLevel = Fixnum.getValue(currentPrintLevel);
208            if (currentLevel >= maxLevel)
209                return "#";
210            sb.append('#');
211            sb.append(dimv.length);
212            sb.append('A');
213            appendContents(dimv, 0, sb, thread);
214            return sb.toString();
215        }
216        sb.append('(');
217        if (this instanceof SimpleArray_T)
218            sb.append("SIMPLE-");
219        sb.append("ARRAY " + getElementType().writeToString() + " (");
220        for (int i = 0; i < dimv.length; i++) {
221            sb.append(dimv[i]);
222            if (i < dimv.length - 1)
223                sb.append(' ');
224        }
225        sb.append("))");
226        return unreadableString(sb.toString());
227    }
228
229    // Helper for writeToString().
230    private void appendContents(int[] dimensions, int index, StringBuilder sb,
231                                LispThread thread)
232
233    {
234        if (dimensions.length == 0) {
235            if (Symbol.PRINT_CIRCLE.symbolValue(thread) != NIL) {
236                StringOutputStream stream = new StringOutputStream();
237                thread.execute(Symbol.OUTPUT_OBJECT.getSymbolFunction(),
238                               AREF(index), stream);
239                sb.append(stream.getString().getStringValue());
240            } else
241                sb.append(AREF(index).writeToString());
242        } else {
243            final LispObject printReadably =
244                Symbol.PRINT_READABLY.symbolValue(thread);
245            int maxLength = Integer.MAX_VALUE;
246            int maxLevel = Integer.MAX_VALUE;
247            if (printReadably == NIL) {
248                final LispObject printLength =
249                    Symbol.PRINT_LENGTH.symbolValue(thread);
250                if (printLength instanceof Fixnum)
251                    maxLength = ((Fixnum)printLength).value;
252                final LispObject printLevel =
253                    Symbol.PRINT_LEVEL.symbolValue(thread);
254                if (printLevel instanceof Fixnum)
255                    maxLevel = ((Fixnum)printLevel).value;
256            }
257            LispObject currentPrintLevel =
258                _CURRENT_PRINT_LEVEL_.symbolValue(thread);
259            int currentLevel = Fixnum.getValue(currentPrintLevel);
260            if (currentLevel < maxLevel) {
261                SpecialBinding lastSpecialBinding = thread.lastSpecialBinding;
262                thread.bindSpecial(_CURRENT_PRINT_LEVEL_, currentPrintLevel.incr());
263                try {
264                    sb.append('(');
265                    int[] dims = new int[dimensions.length - 1];
266                    for (int i = 1; i < dimensions.length; i++)
267                        dims[i-1] = dimensions[i];
268                    int count = 1;
269                    for (int i = 0; i < dims.length; i++)
270                        count *= dims[i];
271                    final int length = dimensions[0];
272                    final int limit = Math.min(length, maxLength);
273                    for (int i = 0; i < limit; i++) {
274                        appendContents(dims, index, sb, thread);
275                        if (i < limit - 1 || limit < length)
276                            sb.append(' ');
277                        index += count;
278                    }
279                    if (limit < length)
280                        sb.append("...");
281                    sb.append(')');
282                }
283                finally {
284                    thread.lastSpecialBinding = lastSpecialBinding;
285                }
286            } else
287                sb.append('#');
288        }
289    }
290
291    // For EQUALP hash tables.
292    @Override
293    public int psxhash()
294    {
295        try {
296            long result = 128387; // Chosen at random.
297            final int rank = getRank();
298            int limit = rank < 4 ? rank : 4;
299            for (int i = 0; i < limit; i++)
300                result = mix(result, getDimension(i));
301            final int length = getTotalSize();
302            limit = length < 4 ? length : 4;
303            for (int i = 0; i < length; i++)
304                result = mix(result, AREF(i).psxhash());
305            return (int) (result & 0x7fffffff);
306        }
307        catch (Throwable t) {
308            // Shouldn't happen.
309            Debug.trace(t);
310            return 0;
311        }
312    }
313
314    /** Returns a newly allocated array or the current array with
315     * adjusted dimensions.
316     *
317     * @param dims
318     * @param initialElement @c null if none
319     * @param initialContents @c null if none
320     * @return @c this or a new array
321     */
322    public abstract AbstractArray adjustArray(int[] dims,
323                                              LispObject initialElement,
324                                              LispObject initialContents);
325
326    /**
327     *
328     * @param dims
329     * @param displacedTo
330     * @param displacement
331     * @return
332     */
333    public abstract AbstractArray adjustArray(int[] dims,
334                                              AbstractArray displacedTo,
335                                              int displacement);
336}
Note: See TracBrowser for help on using the repository browser.