001: /*
002: * Cons.java
003: *
004: * Copyright (C) 2002-2003 Peter Graves
005: * $Id: Cons.java,v 1.6 2003/11/15 11:03:35 beedlem 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 final class Cons extends LispObject {
025: private LispObject car;
026: private LispObject cdr;
027:
028: public Cons(LispObject car, LispObject cdr) {
029: this .car = car;
030: this .cdr = cdr;
031: ++count;
032: }
033:
034: public Cons(LispObject car) {
035: this .car = car;
036: this .cdr = NIL;
037: ++count;
038: }
039:
040: public LispObject typeOf() {
041: return Symbol.CONS;
042: }
043:
044: public LispClass classOf() {
045: return BuiltInClass.CONS;
046: }
047:
048: public LispObject typep(LispObject typeSpecifier)
049: throws ConditionThrowable {
050: if (typeSpecifier == Symbol.LIST)
051: return T;
052: if (typeSpecifier == Symbol.CONS)
053: return T;
054: if (typeSpecifier == Symbol.SEQUENCE)
055: return T;
056: if (typeSpecifier == BuiltInClass.LIST)
057: return T;
058: if (typeSpecifier == BuiltInClass.CONS)
059: return T;
060: if (typeSpecifier == BuiltInClass.SEQUENCE)
061: return T;
062: if (typeSpecifier == Symbol.ATOM)
063: return NIL;
064: return super .typep(typeSpecifier);
065: }
066:
067: public final LispObject CONSTANTP() {
068: if (car == Symbol.QUOTE) {
069: if (cdr instanceof Cons)
070: if (((Cons) cdr).cdr == NIL)
071: return T;
072: }
073: return NIL;
074: }
075:
076: public LispObject ATOM() {
077: return NIL;
078: }
079:
080: public boolean atom() {
081: return false;
082: }
083:
084: public final LispObject car() {
085: return car;
086: }
087:
088: public final LispObject cdr() {
089: return cdr;
090: }
091:
092: public final void setCar(LispObject car) {
093: this .car = car;
094: }
095:
096: public final void setCdr(LispObject cdr) {
097: this .cdr = cdr;
098: }
099:
100: public final LispObject cadr() throws ConditionThrowable {
101: return cdr.car();
102: }
103:
104: public final LispObject cddr() throws ConditionThrowable {
105: return cdr.cdr();
106: }
107:
108: public final int hashCode() {
109: return car.hashCode() ^ cdr.hashCode();
110: }
111:
112: public final boolean equal(LispObject obj)
113: throws ConditionThrowable {
114: if (this == obj)
115: return true;
116: if (obj instanceof Cons) {
117: if (car.equal(((Cons) obj).car)
118: && cdr.equal(((Cons) obj).cdr))
119: return true;
120: }
121: return false;
122: }
123:
124: public final boolean equalp(LispObject obj)
125: throws ConditionThrowable {
126: if (this == obj)
127: return true;
128: if (obj instanceof Cons) {
129: if (car.equalp(((Cons) obj).car)
130: && cdr.equalp(((Cons) obj).cdr))
131: return true;
132: }
133: return false;
134: }
135:
136: public final int length() throws ConditionThrowable {
137: int length = 0;
138: LispObject obj = this ;
139: try {
140: while (obj != NIL) {
141: ++length;
142: obj = ((Cons) obj).cdr;
143: }
144: } catch (ClassCastException e) {
145: throw new ConditionThrowable(new TypeError(obj, "list"));
146: }
147: return length;
148: }
149:
150: public LispObject elt(int index) throws ConditionThrowable {
151: if (index < 0) {
152: throw new ConditionThrowable(new TypeError(
153: "ELT: invalid index " + index + " for " + this ));
154: }
155: int i = 0;
156: Cons cons = this ;
157: try {
158: while (true) {
159: if (i == index)
160: return cons.car;
161: cons = (Cons) cons.cdr;
162: ++i;
163: }
164: } catch (ClassCastException e) {
165: if (cons.cdr == NIL)
166: throw new ConditionThrowable(new TypeError(
167: "ELT: invalid index " + index + " for " + this ));
168: else
169: throw new ConditionThrowable(new TypeError(this ,
170: "proper sequence"));
171: }
172: }
173:
174: public final LispObject nreverse() throws ConditionThrowable {
175: // Following code is adapted from CLISP.
176: if (cdr instanceof Cons) {
177: Cons cons = (Cons) cdr;
178: if (cons.cdr instanceof Cons) {
179: Cons cons1 = cons;
180: LispObject list = NIL;
181: do {
182: Cons h = (Cons) cons.cdr;
183: cons.cdr = list;
184: list = cons;
185: cons = h;
186: } while (cons.cdr instanceof Cons);
187: cdr = list;
188: cons1.cdr = cons;
189: }
190: LispObject h = car;
191: car = cons.car;
192: cons.car = h;
193: }
194: return this ;
195: }
196:
197: public final boolean listp() {
198: return true;
199: }
200:
201: public final LispObject LISTP() {
202: return T;
203: }
204:
205: public final LispObject ENDP() {
206: return NIL;
207: }
208:
209: public LispObject remove(LispObject item) throws ConditionThrowable {
210: LispObject result = NIL;
211: LispObject splice = null;
212: for (LispObject list = this ; list != NIL; list = list.cdr()) {
213: LispObject obj = list.car();
214: if (!obj.eql(item)) {
215: if (splice == null) {
216: splice = new Cons(obj);
217: result = splice;
218: } else {
219: Cons temp = new Cons(obj);
220: splice.setCdr(temp);
221: splice = temp;
222: }
223: }
224: }
225: return result;
226: }
227:
228: public final LispObject[] copyToArray() throws ConditionThrowable {
229: final int length = length();
230: LispObject[] array = new LispObject[length];
231: LispObject rest = this ;
232: for (int i = 0; i < length; i++) {
233: array[i] = rest.car();
234: rest = rest.cdr();
235: }
236: return array;
237: }
238:
239: public String toString() {
240: try {
241: StringBuffer sb = new StringBuffer();
242: if (car == Symbol.QUOTE) {
243: if (cdr instanceof Cons) {
244: // Not a dotted list.
245: if (cdr.cdr() == NIL) {
246: sb.append('\'');
247: sb.append(cdr.car());
248: return sb.toString();
249: }
250: }
251: }
252: if (car == Symbol.FUNCTION) {
253: if (cdr instanceof Cons) {
254: // Not a dotted list.
255: if (cdr.cdr() == NIL) {
256: sb.append("#'");
257: sb.append(cdr.car());
258: return sb.toString();
259: }
260: }
261: }
262: sb.append('(');
263: LispObject p = this ;
264: sb.append(p.car());
265: while ((p = p.cdr()) instanceof Cons) {
266: sb.append(' ');
267: sb.append(p.car());
268: }
269: if (p != NIL) {
270: sb.append(" . ");
271: sb.append(p);
272: }
273: sb.append(')');
274: return sb.toString();
275: } catch (Throwable t) {
276: Debug.trace(t);
277: return "";
278: }
279: }
280:
281: // Statistics for TIME.
282: private static long count;
283:
284: /*package*/static long getCount() {
285: return count;
286: }
287:
288: /*package*/static void setCount(long n) {
289: count = n;
290: }
291: }
|