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

Last change on this file was 15734, checked in by Mark Evenson, 8 months ago

Implement vector-to-vector REPLACE as a primitive

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.9 KB
Line 
1/*
2 * SimpleVector.java
3 *
4 * Copyright (C) 2002-2007 Peter Graves
5 * $Id: SimpleVector.java 15734 2023-09-01 06:28:20Z mevenson $
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 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
38// "The type of a vector that is not displaced to another array, has no fill
39// pointer, is not expressly adjustable and is able to hold elements of any
40// type is a subtype of type SIMPLE-VECTOR."
41public final class SimpleVector extends AbstractVector
42{
43  int capacity;
44  LispObject[] data;
45
46  public SimpleVector(int capacity)
47  {
48    data = new LispObject[capacity];
49    for (int i = capacity; i-- > 0;)
50      data[i] = Fixnum.ZERO;
51    this.capacity = capacity;
52  }
53
54  public SimpleVector(LispObject obj)
55  {
56    if (obj.listp())
57      {
58        data = obj.copyToArray();
59        capacity = data.length;
60      }
61    else if (obj instanceof AbstractVector)
62      {
63        capacity = obj.length();
64        data = new LispObject[capacity];
65        for (int i = 0; i < capacity; i++)
66          data[i] = obj.elt(i);
67      }
68    else
69      Debug.assertTrue(false);
70  }
71
72  public SimpleVector(LispObject[] array)
73  {
74    data = array;
75    capacity = array.length;
76  }
77
78  @Override
79  public LispObject typeOf()
80  {
81    return list(Symbol.SIMPLE_VECTOR, Fixnum.getInstance(capacity));
82  }
83
84  @Override
85  public LispObject classOf()
86  {
87    return BuiltInClass.SIMPLE_VECTOR;
88  }
89
90  @Override
91  public LispObject getDescription()
92  {
93    StringBuffer sb = new StringBuffer("A simple vector with ");
94    sb.append(capacity);
95    sb.append(" elements");
96    return new SimpleString(sb);
97  }
98
99  @Override
100  public LispObject typep(LispObject type)
101  {
102    if (type == Symbol.SIMPLE_VECTOR)
103      return T;
104    if (type == Symbol.SIMPLE_ARRAY)
105      return T;
106    if (type == BuiltInClass.SIMPLE_VECTOR)
107      return T;
108    if (type == BuiltInClass.SIMPLE_ARRAY)
109      return T;
110    return super.typep(type);
111  }
112
113  @Override
114  public LispObject getElementType()
115  {
116    return T;
117  }
118
119  @Override
120  public boolean isSimpleVector()
121  {
122    return true;
123  }
124
125  @Override
126  public boolean hasFillPointer()
127  {
128    return false;
129  }
130
131  @Override
132  public boolean isAdjustable()
133  {
134    return false;
135  }
136
137  @Override
138  public int capacity()
139  {
140    return capacity;
141  }
142
143  @Override
144  public int length()
145  {
146    return capacity;
147  }
148
149  @Override
150  public LispObject elt(int index)
151  {
152    try
153      {
154        return data[index];
155      }
156    catch (ArrayIndexOutOfBoundsException e)
157      {
158        badIndex(index, capacity);
159        return NIL; // Not reached.
160      }
161  }
162
163  @Override
164  public LispObject AREF(int index)
165  {
166    try
167      {
168        return data[index];
169      }
170    catch (ArrayIndexOutOfBoundsException e)
171      {
172        badIndex(index, data.length);
173        return NIL; // Not reached.
174      }
175  }
176
177  @Override
178  public void aset(int index, LispObject newValue)
179  {
180    try
181      {
182        data[index] = newValue;
183      }
184    catch (ArrayIndexOutOfBoundsException e)
185      {
186        badIndex(index, capacity);
187      }
188  }
189
190  @Override
191  public LispObject SVREF(int index)
192  {
193    try
194      {
195        return data[index];
196      }
197    catch (ArrayIndexOutOfBoundsException e)
198      {
199        badIndex(index, data.length);
200        return NIL; // Not reached.
201      }
202  }
203
204  @Override
205  public void svset(int index, LispObject newValue)
206  {
207    try
208      {
209        data[index] = newValue;
210      }
211    catch (ArrayIndexOutOfBoundsException e)
212      {
213        badIndex(index, capacity);
214      }
215  }
216
217  @Override
218  public LispObject subseq(int start, int end)
219  {
220    SimpleVector v = new SimpleVector(end - start);
221    int i = start, j = 0;
222    try
223      {
224        while (i < end)
225          v.data[j++] = data[i++];
226        return v;
227      }
228    catch (ArrayIndexOutOfBoundsException e)
229      {
230        return error(new TypeError("Array index out of bounds: " + i + "."));
231      }
232  }
233
234  @Override
235  public void fill(LispObject obj)
236  {
237    for (int i = capacity; i-- > 0;)
238      data[i] = obj;
239  }
240
241  @Override
242  public LispObject deleteEq(LispObject item)
243  {
244    final int limit = capacity;
245    int i = 0;
246    int j = 0;
247    while (i < limit)
248      {
249        LispObject obj = data[i++];
250        if (obj != item)
251          data[j++] = obj;
252      }
253    if (j < limit)
254      shrink(j);
255    return this;
256  }
257
258  @Override
259  public LispObject deleteEql(LispObject item)
260  {
261    final int limit = capacity;
262    int i = 0;
263    int j = 0;
264    while (i < limit)
265      {
266        LispObject obj = data[i++];
267        if (!obj.eql(item))
268          data[j++] = obj;
269      }
270    if (j < limit)
271      shrink(j);
272    return this;
273  }
274
275  @Override
276  public void shrink(int n)
277  {
278    if (n < capacity)
279      {
280        LispObject[] newData = new LispObject[n];
281        System.arraycopy(data, 0, newData, 0, n);
282        data = newData;
283        capacity = n;
284        return;
285      }
286    if (n == capacity)
287      return;
288    error(new LispError());
289  }
290
291  @Override
292  public LispObject reverse()
293  {
294    SimpleVector result = new SimpleVector(capacity);
295    int i, j;
296    for (i = 0, j = capacity - 1; i < capacity; i++, j--)
297      result.data[i] = data[j];
298    return result;
299  }
300
301  @Override
302  public LispObject nreverse()
303  {
304    int i = 0;
305    int j = capacity - 1;
306    while (i < j)
307      {
308        LispObject temp = data[i];
309        data[i] = data[j];
310        data[j] = temp;
311        ++i;
312        --j;
313      }
314    return this;
315  }
316
317  @Override
318  public AbstractVector adjustArray(int newCapacity,
319                                     LispObject initialElement,
320                                     LispObject initialContents)
321
322  {
323    if (initialContents != null)
324      {
325        LispObject[] newData = new LispObject[newCapacity];
326        if (initialContents.listp())
327          {
328            LispObject list = initialContents;
329            for (int i = 0; i < newCapacity; i++)
330              {
331                newData[i] = list.car();
332                list = list.cdr();
333              }
334          }
335        else if (initialContents.vectorp())
336          {
337            for (int i = 0; i < newCapacity; i++)
338              newData[i] = initialContents.elt(i);
339          }
340        else
341          type_error(initialContents, Symbol.SEQUENCE);
342        return new SimpleVector(newData);
343      }
344    if (capacity != newCapacity)
345      {
346        LispObject[] newData = new LispObject[newCapacity];
347        System.arraycopy(data, 0, newData, 0,
348                         Math.min(capacity, newCapacity));
349        if (initialElement != null)
350            for (int i = capacity; i < newCapacity; i++)
351                newData[i] = initialElement;
352        return new SimpleVector(newData);
353      }
354    // No change.
355    return this;
356  }
357
358  @Override
359  public AbstractVector adjustArray(int newCapacity,
360                                     AbstractArray displacedTo,
361                                     int displacement)
362  {
363    return new ComplexVector(newCapacity, displacedTo, displacement);
364  }
365
366  @Override
367  public AbstractVector replace(AbstractVector source,
368                                int targetStart, int targetEnd,
369                                int sourceStart, int sourceEnd)
370  {
371    if (source instanceof SimpleVector) {
372      System.arraycopy(((SimpleVector)source).data, sourceStart,
373                       data, targetStart,
374                       Math.min(targetEnd - targetStart, sourceEnd - sourceStart));
375      return this;
376    } else {
377      return super.replace(source, targetStart, targetEnd, sourceStart, sourceEnd);
378    }
379  }
380
381  // ### svref
382  // svref simple-vector index => element
383  private static final Primitive SVREF =
384    new Primitive("svref", "simple-vector index")
385    {
386      @Override
387      public LispObject execute(LispObject first, LispObject second)
388
389      {
390                        if (first instanceof SimpleVector) {
391                                final SimpleVector sv = (SimpleVector)first;
392                    int index = Fixnum.getValue(second);
393                                try {
394                                        return sv.data[index];
395                                } catch (ArrayIndexOutOfBoundsException e) {
396                                        int capacity = sv.capacity;
397                                         sv.badIndex(index, capacity);
398                                        // Not reached.
399                                        return NIL;
400                                }
401                        }
402                        return type_error(first, Symbol.SIMPLE_VECTOR);
403                }
404    };
405
406  // ### svset simple-vector index new-value => new-value
407  private static final Primitive SVSET =
408    new Primitive("svset", PACKAGE_SYS, true, "simple-vector index new-value")
409    {
410      @Override
411      public LispObject execute(LispObject first, LispObject second,
412                                LispObject third)
413
414      {
415                        if (first instanceof SimpleVector) {
416                                final SimpleVector sv = (SimpleVector)first;
417                    int index = Fixnum.getValue(second);
418                                try {
419                                        sv.data[index] = third;
420                                        return third;
421                                } catch (ArrayIndexOutOfBoundsException e) {
422                                        int capacity = sv.capacity;
423                                         sv.badIndex(index, capacity);
424                                        // Not reached.
425                                        return NIL;
426                                }
427                        }
428                        return type_error(first, Symbol.SIMPLE_VECTOR);
429      }
430    };
431}
Note: See TracBrowser for help on using the repository browser.