source: trunk/abcl/src/org/armedbear/lisp/AbstractArray.java

Last change on this file was 14465, checked in by rschlatte, 11 years ago

new method program_error, analogous to type_error

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 11.1 KB
Line 
1/*
2 * AbstractArray.java
3 *
4 * Copyright (C) 2003-2005 Peter Graves
5 * $Id: AbstractArray.java 14465 2013-04-24 12:50:37Z rschlatte $
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
36import static org.armedbear.lisp.Lisp.*;
37
38public abstract class AbstractArray extends LispObject implements java.io.Serializable
39{
40    @Override
41    public LispObject typep(LispObject type)
42    {
43        if (type == Symbol.ARRAY)
44            return T;
45        if (type == BuiltInClass.ARRAY)
46            return T;
47        return super.typep(type);
48    }
49
50    @Override
51    public boolean equalp(LispObject obj)
52    {
53        if (obj instanceof AbstractArray) {
54            AbstractArray a = (AbstractArray) obj;
55            if (getRank() != a.getRank())
56                return false;
57            for (int i = getRank(); i-- > 0;) {
58                if (getDimension(i) != a.getDimension(i))
59                    return false;
60            }
61            for (int i = getTotalSize(); i--> 0;) {
62                if (!AREF(i).equalp(a.AREF(i)))
63                    return false;
64            }
65            return true;
66        }
67        return false;
68    }
69
70    public boolean isDisplaced()
71    {
72        return false;
73    }
74
75    public LispObject arrayDisplacement()
76    {
77        return LispThread.currentThread().setValues(NIL, Fixnum.ZERO);
78    }
79
80    public boolean hasFillPointer()
81    {
82        return false;
83    }
84
85    public int getFillPointer()
86    {
87        noFillPointer();
88        return -1; // Not reached.
89    }
90
91    public void setFillPointer(LispObject fillPointer)
92    {
93        setFillPointer(fillPointer.intValue());
94    }
95
96    public void setFillPointer(int fillPointer)
97    {
98        noFillPointer();
99    }
100
101    public boolean isAdjustable()
102    {
103        return true;
104    }
105
106    public abstract int getRank();
107
108    public abstract LispObject getDimensions();
109
110    public abstract int getDimension(int n);
111
112    public abstract LispObject getElementType();
113
114    public abstract int getTotalSize();
115
116    @Override
117    public abstract void aset(int index, LispObject newValue)
118       ;
119
120    // FIXME Detect overflow!
121    protected static final int computeTotalSize(int[] dimensions)
122    {
123        int size = 1;
124        for (int i = dimensions.length; i-- > 0;)
125            size *= dimensions[i];
126        return size;
127    }
128
129    public int getRowMajorIndex(LispObject[] subscripts)
130
131    {
132        int[] subs = new int[subscripts.length];
133        for (int i = 0; i < subscripts.length; i++) {
134            LispObject subscript = subscripts[i];
135            if (subscript instanceof Fixnum)
136                subs[i] = ((Fixnum)subscript).value;
137            else
138                type_error(subscript, Symbol.FIXNUM);
139        }
140        return getRowMajorIndex(subs);
141    }
142
143    public int getRowMajorIndex(int[] subscripts)
144    {
145        final int rank = getRank();
146        if (rank != subscripts.length) {
147            // ### i18n
148            final String errorMsg =
149                "Wrong number of subscripts (%d) for array of rank %d.";
150            program_error(String.format(errorMsg, subscripts.length, rank));
151        }
152        int sum = 0;
153        int size = 1;
154        for (int i = rank; i-- > 0;) {
155            final int dim = getDimension(i);
156            final int lastSize = size;
157            size *= dim;
158            final int n = subscripts[i];
159            if (n < 0 || n >= dim) {
160                // ### i18n
161                final String errorMsg =
162                    "Invalid index %d for array %s.";
163                program_error(String.format(errorMsg, n, printObject()));
164            }
165            sum += n * lastSize;
166        }
167        return sum;
168    }
169
170    public LispObject get(int[] subscripts)
171    {
172        return AREF(getRowMajorIndex(subscripts));
173    }
174
175    public void set(int[] subscripts, LispObject newValue)
176
177    {
178        aset(getRowMajorIndex(subscripts), newValue);
179    }
180
181    public abstract void fill(LispObject obj);
182
183    public String printObject(int[] dimv)
184    {
185        StringBuilder sb = new StringBuilder();
186        LispThread thread = LispThread.currentThread();
187        LispObject printReadably = Symbol.PRINT_READABLY.symbolValue(thread);
188        if (printReadably != NIL || Symbol.PRINT_ARRAY.symbolValue(thread) != NIL) {
189            int maxLevel = Integer.MAX_VALUE;
190            if (printReadably != NIL) {
191                for (int i = 0; i < dimv.length - 1; i++) {
192                    if (dimv[i] == 0) {
193                        for (int j = i + 1; j < dimv.length; j++) {
194                            if (dimv[j] != 0) {
195                                error(new PrintNotReadable(list(Keyword.OBJECT,
196                                                                  this)));
197                                return null; // Not reached.
198                            }
199                        }
200                    }
201                }
202            } else {
203                LispObject printLevel = Symbol.PRINT_LEVEL.symbolValue(thread);
204                if (printLevel instanceof Fixnum)
205                    maxLevel = ((Fixnum)printLevel).value;
206            }
207            LispObject currentPrintLevel =
208                _CURRENT_PRINT_LEVEL_.symbolValue(thread);
209            int currentLevel = Fixnum.getValue(currentPrintLevel);
210            if (currentLevel >= maxLevel)
211                return "#";
212            sb.append('#');
213            sb.append(dimv.length);
214            sb.append('A');
215            appendContents(dimv, 0, sb, thread);
216            return sb.toString();
217        }
218        sb.append('(');
219        if (this instanceof SimpleArray_T)
220            sb.append("SIMPLE-");
221        sb.append("ARRAY " + getElementType().printObject() + " (");
222        for (int i = 0; i < dimv.length; i++) {
223            sb.append(dimv[i]);
224            if (i < dimv.length - 1)
225                sb.append(' ');
226        }
227        sb.append("))");
228        return unreadableString(sb.toString());
229    }
230
231    // Helper for printObject().
232    private void appendContents(int[] dimensions, int index, StringBuilder sb,
233                                LispThread thread)
234
235    {
236        if (dimensions.length == 0) {
237            if (Symbol.PRINT_CIRCLE.symbolValue(thread) != NIL) {
238                StringOutputStream stream = new StringOutputStream();
239                thread.execute(Symbol.OUTPUT_OBJECT.getSymbolFunction(),
240                               AREF(index), stream);
241                sb.append(stream.getString().getStringValue());
242            } else
243                sb.append(AREF(index).printObject());
244        } else {
245            final LispObject printReadably =
246                Symbol.PRINT_READABLY.symbolValue(thread);
247            int maxLength = Integer.MAX_VALUE;
248            int maxLevel = Integer.MAX_VALUE;
249            if (printReadably == NIL) {
250                final LispObject printLength =
251                    Symbol.PRINT_LENGTH.symbolValue(thread);
252                if (printLength instanceof Fixnum)
253                    maxLength = ((Fixnum)printLength).value;
254                final LispObject printLevel =
255                    Symbol.PRINT_LEVEL.symbolValue(thread);
256                if (printLevel instanceof Fixnum)
257                    maxLevel = ((Fixnum)printLevel).value;
258            }
259            LispObject currentPrintLevel =
260                _CURRENT_PRINT_LEVEL_.symbolValue(thread);
261            int currentLevel = Fixnum.getValue(currentPrintLevel);
262            if (currentLevel < maxLevel) {
263                final SpecialBindingsMark mark = thread.markSpecialBindings();
264                thread.bindSpecial(_CURRENT_PRINT_LEVEL_, currentPrintLevel.incr());
265                try {
266                    sb.append('(');
267                    int[] dims = new int[dimensions.length - 1];
268                    for (int i = 1; i < dimensions.length; i++)
269                        dims[i-1] = dimensions[i];
270                    int count = 1;
271                    for (int i = 0; i < dims.length; i++)
272                        count *= dims[i];
273                    final int length = dimensions[0];
274                    final int limit = Math.min(length, maxLength);
275                    for (int i = 0; i < limit; i++) {
276                        appendContents(dims, index, sb, thread);
277                        if (i < limit - 1 || limit < length)
278                            sb.append(' ');
279                        index += count;
280                    }
281                    if (limit < length)
282                        sb.append("...");
283                    sb.append(')');
284                }
285                finally {
286                    thread.resetSpecialBindings(mark);
287                }
288            } else
289                sb.append('#');
290        }
291    }
292
293    // For EQUALP hash tables.
294    @Override
295    public int psxhash()
296    {
297        long result = 128387; // Chosen at random.
298        final int rank = getRank();
299        int limit = rank < 4 ? rank : 4;
300        for (int i = 0; i < limit; i++)
301            result = mix(result, getDimension(i));
302        final int length = getTotalSize();
303        limit = length < 4 ? length : 4;
304        for (int i = 0; i < length; i++)
305            result = mix(result, AREF(i).psxhash());
306        return (int) (result & 0x7fffffff);
307    }
308
309    /** Returns a newly allocated array or the current array with
310     * adjusted dimensions.
311     *
312     * @param dims
313     * @param initialElement @c null if none
314     * @param initialContents @c null if none
315     * @return @c this or a new array
316     */
317    public abstract AbstractArray adjustArray(int[] dims,
318                                              LispObject initialElement,
319                                              LispObject initialContents);
320
321    /**
322     *
323     * @param dims
324     * @param displacedTo
325     * @param displacement
326     * @return
327     */
328    public abstract AbstractArray adjustArray(int[] dims,
329                                              AbstractArray displacedTo,
330                                              int displacement);
331}
Note: See TracBrowser for help on using the repository browser.