001: /*
002: * AbstractArray.java
003: *
004: * Copyright (C) 2003-2004 Peter Graves
005: * $Id: AbstractArray.java,v 1.26 2004/05/27 20:44:59 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.lisp;
023:
024: public abstract class AbstractArray extends LispObject {
025: public LispObject typep(LispObject type) throws ConditionThrowable {
026: if (type == Symbol.ARRAY)
027: return T;
028: if (type == BuiltInClass.ARRAY)
029: return T;
030: return super .typep(type);
031: }
032:
033: public boolean equalp(LispObject obj) throws ConditionThrowable {
034: if (obj instanceof AbstractArray) {
035: AbstractArray a = (AbstractArray) obj;
036: if (getRank() != a.getRank())
037: return false;
038: for (int i = getRank(); i-- > 0;) {
039: if (getDimension(i) != a.getDimension(i))
040: return false;
041: }
042: for (int i = getTotalSize(); i-- > 0;) {
043: if (!getRowMajor(i).equalp(a.getRowMajor(i)))
044: return false;
045: }
046: return true;
047: }
048: return false;
049: }
050:
051: public boolean isDisplaced() {
052: return false;
053: }
054:
055: public LispObject arrayDisplacement() throws ConditionThrowable {
056: return LispThread.currentThread().setValues(NIL, Fixnum.ZERO);
057: }
058:
059: public boolean hasFillPointer() {
060: return false;
061: }
062:
063: public int getFillPointer() throws ConditionThrowable {
064: noFillPointer();
065: return -1; // Not reached.
066: }
067:
068: public boolean isAdjustable() {
069: return true;
070: }
071:
072: public LispObject AREF(LispObject index) throws ConditionThrowable {
073: StringBuffer sb = new StringBuffer("AREF: ");
074: sb.append("wrong number of subscripts (1) for array of rank ");
075: sb.append(getRank());
076: sb.append(".");
077: return signal(new ProgramError(sb.toString()));
078: }
079:
080: public abstract int getRank();
081:
082: public abstract LispObject getDimensions();
083:
084: public abstract int getDimension(int n) throws ConditionThrowable;
085:
086: public abstract LispObject getElementType();
087:
088: public abstract int getTotalSize();
089:
090: public abstract LispObject getRowMajor(int index)
091: throws ConditionThrowable;
092:
093: public abstract void setRowMajor(int index, LispObject newValue)
094: throws ConditionThrowable;
095:
096: // FIXME Detect overflow!
097: protected static final int computeTotalSize(int[] dimensions) {
098: int size = 1;
099: for (int i = dimensions.length; i-- > 0;)
100: size *= dimensions[i];
101: return size;
102: }
103:
104: public int getRowMajorIndex(LispObject[] subscripts)
105: throws ConditionThrowable {
106: int[] subs = new int[subscripts.length];
107: for (int i = 0; i < subscripts.length; i++) {
108: LispObject subscript = subscripts[i];
109: if (subscript instanceof Fixnum)
110: subs[i] = ((Fixnum) subscript).value;
111: else
112: signal(new TypeError(subscript, Symbol.FIXNUM));
113: }
114: return getRowMajorIndex(subs);
115: }
116:
117: public int getRowMajorIndex(int[] subscripts)
118: throws ConditionThrowable {
119: final int rank = getRank();
120: if (rank != subscripts.length) {
121: StringBuffer sb = new StringBuffer(
122: "Wrong number of subscripts (");
123: sb.append(subscripts.length);
124: sb.append(") for array of rank ");
125: sb.append(rank);
126: sb.append('.');
127: signal(new ProgramError(sb.toString()));
128: }
129: int sum = 0;
130: int size = 1;
131: for (int i = rank; i-- > 0;) {
132: int dim = getDimension(i);
133: int lastSize = size;
134: size *= dim;
135: int n = subscripts[i];
136: if (n < 0 || n >= getDimension(i)) {
137: StringBuffer sb = new StringBuffer("Invalid index ");
138: sb.append(n);
139: sb.append(" for array ");
140: sb.append(this );
141: sb.append('.');
142: signal(new ProgramError(sb.toString()));
143: }
144: sum += n * lastSize;
145: }
146: return sum;
147: }
148:
149: public LispObject get(int[] subscripts) throws ConditionThrowable {
150: return getRowMajor(getRowMajorIndex(subscripts));
151: }
152:
153: public void set(int[] subscripts, LispObject newValue)
154: throws ConditionThrowable {
155: setRowMajor(getRowMajorIndex(subscripts), newValue);
156: }
157:
158: public abstract void fill(LispObject obj) throws ConditionThrowable;
159:
160: // Helper for toString().
161: protected void appendContents(int[] dimensions, int index,
162: StringBuffer sb) throws ConditionThrowable {
163: try {
164: if (dimensions.length == 0) {
165: sb.append(getRowMajor(index).writeToString());
166: } else {
167: sb.append('(');
168: int[] dims = new int[dimensions.length - 1];
169: for (int i = 1; i < dimensions.length; i++)
170: dims[i - 1] = dimensions[i];
171: int count = 1;
172: for (int i = 0; i < dims.length; i++)
173: count *= dims[i];
174: int length = dimensions[0];
175: for (int i = 0; i < length; i++) {
176: if (i != 0)
177: sb.append(' ');
178: appendContents(dims, index, sb);
179: index += count;
180: }
181: sb.append(')');
182: }
183: } catch (ConditionThrowable t) {
184: Debug.trace(t);
185: }
186: }
187:
188: public final LispObject noFillPointer() throws ConditionThrowable {
189: return signal(new TypeError(
190: "Array does not have a fill pointer."));
191: }
192: }
|