KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > lisp > Primitives


1 /*
2  * Primitives.java
3  *
4  * Copyright (C) 2002-2004 Peter Graves
5  * $Id: Primitives.java,v 1.681 2004/09/21 18:14:45 piso Exp $
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
22 package org.armedbear.lisp;
23
24 import java.io.File JavaDoc;
25 import java.math.BigInteger JavaDoc;
26 import java.util.ArrayList JavaDoc;
27
28 public final class Primitives extends Lisp
29 {
30     // ### *
31
public static final Primitive MULTIPLY = new Primitive("*","&rest numbers")
32     {
33         public LispObject execute()
34         {
35             return Fixnum.ONE;
36         }
37         public LispObject execute(LispObject arg) throws ConditionThrowable
38         {
39             if (arg.numberp())
40                 return arg;
41             signal(new TypeError(arg, "number"));
42             return NIL;
43         }
44         public LispObject execute(LispObject first, LispObject second)
45             throws ConditionThrowable
46         {
47             return first.multiplyBy(second);
48         }
49         public LispObject execute(LispObject[] args) throws ConditionThrowable
50         {
51             LispObject result = Fixnum.ONE;
52             for (int i = 0; i < args.length; i++)
53                 result = result.multiplyBy(args[i]);
54             return result;
55         }
56     };
57
58     // ### /
59
public static final Primitive DIVIDE = new Primitive("/","numerator &rest denominators")
60     {
61         public LispObject execute() throws ConditionThrowable
62         {
63             signal(new WrongNumberOfArgumentsException("/"));
64             return NIL;
65         }
66         public LispObject execute(LispObject arg) throws ConditionThrowable
67         {
68             return Fixnum.ONE.divideBy(arg);
69         }
70         public LispObject execute(LispObject first, LispObject second)
71             throws ConditionThrowable
72         {
73             return first.divideBy(second);
74         }
75         public LispObject execute(LispObject[] args) throws ConditionThrowable
76         {
77             LispObject result = args[0];
78             for (int i = 1; i < args.length; i++)
79                 result = result.divideBy(args[i]);
80             return result;
81         }
82     };
83
84     // ### min
85
public static final Primitive MIN = new Primitive("min","&rest reals")
86     {
87         public LispObject execute() throws ConditionThrowable
88         {
89             signal(new WrongNumberOfArgumentsException("min"));
90             return NIL;
91         }
92         public LispObject execute(LispObject arg) throws ConditionThrowable
93         {
94             if (arg.realp())
95                 return arg;
96             signal(new TypeError(arg, "real number"));
97             return NIL;
98         }
99         public LispObject execute(LispObject[] args) throws ConditionThrowable
100         {
101             LispObject result = args[0];
102             if (!result.realp())
103                 signal(new TypeError(result, "real number"));
104             for (int i = 1; i < args.length; i++) {
105                 if (args[i].isLessThan(result))
106                     result = args[i];
107             }
108             return result;
109         }
110     };
111
112
113     // ### max
114
public static final Primitive MAX = new Primitive("max","&rest reals")
115     {
116         public LispObject execute() throws ConditionThrowable
117         {
118             signal(new WrongNumberOfArgumentsException("max"));
119             return NIL;
120         }
121         public LispObject execute(LispObject arg) throws ConditionThrowable
122         {
123             if (arg.realp())
124                 return arg;
125             signal(new TypeError(arg, "real number"));
126             return NIL;
127         }
128         public LispObject execute(LispObject[] args) throws ConditionThrowable
129         {
130             LispObject result = args[0];
131             if (!result.realp())
132                 signal(new TypeError(result, "real number"));
133             for (int i = 1; i < args.length; i++) {
134                 if (args[i].isGreaterThan(result))
135                     result = args[i];
136             }
137             return result;
138         }
139     };
140
141     // ### identity
142
private static final Primitive1 IDENTITY = new Primitive1("identity","object")
143     {
144         public LispObject execute(LispObject arg) throws ConditionThrowable
145         {
146             return arg;
147         }
148     };
149
150     // ### compiled-function-p
151
private static final Primitive1 COMPILED_FUNCTION_P =
152         new Primitive1("compiled-function-p","object")
153     {
154         public LispObject execute(LispObject arg) throws ConditionThrowable
155         {
156             return arg.typep(Symbol.COMPILED_FUNCTION);
157         }
158     };
159
160     // ### consp
161
private static final Primitive1 CONSP = new Primitive1("consp","object")
162     {
163         public LispObject execute(LispObject arg) throws ConditionThrowable
164         {
165             return arg instanceof Cons ? T : NIL;
166         }
167     };
168
169     // ### listp
170
private static final Primitive1 LISTP = new Primitive1("listp","object")
171     {
172         public LispObject execute(LispObject arg) throws ConditionThrowable
173         {
174             return arg.LISTP();
175         }
176     };
177
178     // ### abs
179
private static final Primitive1 ABS = new Primitive1("abs","number")
180     {
181         public LispObject execute(LispObject arg) throws ConditionThrowable
182         {
183             return arg.ABS();
184         }
185     };
186
187     // ### arrayp
188
private static final Primitive1 ARRAYP = new Primitive1("arrayp","object")
189     {
190         public LispObject execute(LispObject arg) throws ConditionThrowable
191         {
192             return arg instanceof AbstractArray ? T : NIL;
193         }
194     };
195
196     // ### array-has-fill-pointer-p
197
private static final Primitive1 ARRAY_HAS_FILL_POINTER_P =
198         new Primitive1("array-has-fill-pointer-p", "array")
199     {
200         public LispObject execute(LispObject arg) throws ConditionThrowable
201         {
202             try {
203                 return ((AbstractArray)arg).hasFillPointer() ? T : NIL;
204             }
205             catch (ClassCastException JavaDoc e) {
206                 return signal(new TypeError(arg, Symbol.ARRAY));
207             }
208         }
209     };
210
211     // ### vectorp
212
private static final Primitive1 VECTORP = new Primitive1("vectorp", "object")
213     {
214         public LispObject execute(LispObject arg) throws ConditionThrowable
215         {
216             return arg.VECTORP();
217         }
218     };
219
220     // ### simple-vector-p
221
private static final Primitive1 SIMPLE_VECTOR_P =
222         new Primitive1("simple-vector-p", "object")
223     {
224         public LispObject execute(LispObject arg) throws ConditionThrowable
225         {
226             return arg instanceof SimpleVector ? T : NIL;
227         }
228     };
229
230     // ### bit-vector-p
231
private static final Primitive1 BIT_VECTOR_P =
232         new Primitive1("bit-vector-p", "object")
233     {
234         public LispObject execute(LispObject arg) throws ConditionThrowable
235         {
236             return arg.BIT_VECTOR_P();
237         }
238     };
239
240     // ### simple-bit-vector-p
241
private static final Primitive1 SIMPLE_BIT_VECTOR_P =
242         new Primitive1("simple-bit-vector-p", "object")
243     {
244         public LispObject execute(LispObject arg) throws ConditionThrowable
245         {
246             return arg.typep(Symbol.SIMPLE_BIT_VECTOR);
247         }
248     };
249
250     // ### %eval
251
private static final Primitive1 _EVAL =
252         new Primitive1("%eval", PACKAGE_SYS, false, "form")
253     {
254         public LispObject execute(LispObject arg) throws ConditionThrowable
255         {
256             return eval(arg, new Environment(), LispThread.currentThread());
257         }
258     };
259
260     // ### eq
261
private static final Primitive2 EQ = new Primitive2("eq", "x y")
262     {
263         public LispObject execute(LispObject first, LispObject second)
264             throws ConditionThrowable
265         {
266             return first == second ? T : NIL;
267         }
268     };
269
270     // ### eql
271
private static final Primitive2 EQL = new Primitive2("eql", "x y")
272     {
273         public LispObject execute(LispObject first, LispObject second)
274             throws ConditionThrowable
275         {
276             return first.eql(second) ? T : NIL;
277         }
278     };
279
280     // ### equal
281
private static final Primitive2 EQUAL = new Primitive2("equal", "x y")
282     {
283         public LispObject execute(LispObject first, LispObject second)
284             throws ConditionThrowable
285         {
286             return first.equal(second) ? T : NIL;
287         }
288     };
289
290     // ### equalp
291
private static final Primitive2 EQUALP = new Primitive2("equalp", "x y")
292     {
293         public LispObject execute(LispObject first, LispObject second)
294             throws ConditionThrowable
295         {
296             return first.equalp(second) ? T : NIL;
297         }
298     };
299
300     // ### values
301
private static final Primitive VALUES = new Primitive("values", "&rest object")
302     {
303         public LispObject execute()
304             throws ConditionThrowable
305         {
306             return LispThread.currentThread().setValues();
307         }
308         public LispObject execute(LispObject arg)
309             throws ConditionThrowable
310         {
311             return LispThread.currentThread().setValues(arg);
312         }
313         public LispObject execute(LispObject first, LispObject second)
314             throws ConditionThrowable
315         {
316             return LispThread.currentThread().setValues(first, second);
317         }
318         public LispObject execute(LispObject first, LispObject second,
319                                   LispObject third)
320             throws ConditionThrowable
321         {
322             return LispThread.currentThread().setValues(first, second, third);
323         }
324         public LispObject execute(LispObject[] args)
325             throws ConditionThrowable
326         {
327             return LispThread.currentThread().setValues(args);
328         }
329     };
330
331     // ### values-list
332
// values-list list => element*
333
// Returns the elements of the list as multiple values.
334
private static final Primitive1 VALUES_LIST =
335         new Primitive1("values-list", "list")
336     {
337         public LispObject execute(LispObject arg) throws ConditionThrowable
338         {
339             return LispThread.currentThread().setValues(arg.copyToArray());
340         }
341     };
342
343     // ### cons
344
private static final Primitive2 CONS =
345         new Primitive2("cons", "object-1 object-2")
346     {
347         public LispObject execute(LispObject first, LispObject second)
348             throws ConditionThrowable
349         {
350             return new Cons(first, second);
351         }
352     };
353
354     // ### length
355
private static final Primitive1 LENGTH =
356         new Primitive1("length", "sequence")
357     {
358         public LispObject execute(LispObject arg) throws ConditionThrowable
359         {
360             return arg.LENGTH();
361         }
362     };
363
364     // ### elt
365
private static final Primitive2 ELT =
366         new Primitive2("elt", "sequence index")
367     {
368         public LispObject execute(LispObject first, LispObject second)
369             throws ConditionThrowable
370         {
371             try {
372                 return first.elt(((Fixnum)second).value);
373             }
374             catch (ClassCastException JavaDoc e) {
375                 return signal(new TypeError(second, Symbol.FIXNUM));
376             }
377         }
378     };
379
380     // ### atom
381
private static final Primitive1 ATOM = new Primitive1("atom", "object")
382     {
383         public LispObject execute(LispObject arg) throws ConditionThrowable
384         {
385             return arg instanceof Cons ? NIL : T;
386         }
387     };
388
389     // ### constantp
390
private static final Primitive CONSTANTP =
391         new Primitive("constantp", "form &optional environment")
392     {
393         public LispObject execute(LispObject arg) throws ConditionThrowable
394         {
395             return arg.constantp() ? T : NIL;
396         }
397         public LispObject execute(LispObject first, LispObject second)
398             throws ConditionThrowable
399         {
400             return first.constantp() ? T : NIL;
401         }
402     };
403
404     // ### functionp
405
private static final Primitive1 FUNCTIONP = new Primitive1("functionp","object")
406     {
407         public LispObject execute(LispObject arg) throws ConditionThrowable
408         {
409             return (arg instanceof Function || arg instanceof GenericFunction) ? T : NIL;
410         }
411     };
412
413     // ### special-operator-p
414
private static final Primitive1 SPECIAL_OPERATOR_P =
415         new Primitive1("special-operator-p","symbol")
416     {
417         public LispObject execute(LispObject arg) throws ConditionThrowable
418         {
419             return arg.getSymbolFunction() instanceof SpecialOperator ? T : NIL;
420         }
421     };
422
423     // ### symbolp
424
private static final Primitive1 SYMBOLP = new Primitive1("symbolp", "object")
425     {
426         public LispObject execute(LispObject arg) throws ConditionThrowable
427         {
428             return arg instanceof Symbol ? T : NIL;
429         }
430     };
431
432     // ### endp
433
private static final Primitive1 ENDP = new Primitive1("endp", "list")
434     {
435         public LispObject execute(LispObject arg) throws ConditionThrowable
436         {
437             return arg.endp() ? T : NIL;
438         }
439     };
440
441     // ### null
442
private static final Primitive1 NULL = new Primitive1("null", "object")
443     {
444         public LispObject execute(LispObject arg) throws ConditionThrowable
445         {
446             return arg == NIL ? T : NIL;
447         }
448     };
449
450     // ### not
451
private static final Primitive1 NOT = new Primitive1("not", "x")
452     {
453         public LispObject execute(LispObject arg) throws ConditionThrowable
454         {
455             return arg == NIL ? T : NIL;
456         }
457     };
458
459     // ### plusp
460
private static final Primitive1 PLUSP = new Primitive1("plusp", "real")
461     {
462         public LispObject execute(LispObject arg) throws ConditionThrowable
463         {
464             return arg.PLUSP();
465         }
466     };
467
468     // ### minusp
469
private static final Primitive1 MINUSP = new Primitive1("minusp", "real")
470     {
471         public LispObject execute(LispObject arg) throws ConditionThrowable
472         {
473             return arg.MINUSP();
474         }
475     };
476
477     // ### zerop
478
private static final Primitive1 ZEROP = new Primitive1("zerop","number") {
479         public LispObject execute(LispObject arg) throws ConditionThrowable
480         {
481             return arg.ZEROP();
482         }
483     };
484
485     // ### fixnump
486
private static final Primitive1 FIXNUMP =
487         new Primitive1("fixnump", PACKAGE_EXT, true) {
488         public LispObject execute(LispObject arg) throws ConditionThrowable
489         {
490             return arg instanceof Fixnum ? T : NIL;
491         }
492     };
493
494     // ### symbol-value
495
private static final Primitive1 SYMBOL_VALUE =
496         new Primitive1("symbol-value", "symbol")
497     {
498         public LispObject execute(LispObject arg) throws ConditionThrowable
499         {
500             final Symbol symbol = checkSymbol(arg);
501             LispObject value =
502                 LispThread.currentThread().lookupSpecial(symbol);
503             if (value == null) {
504                 value = symbol.symbolValue();
505                 if (value instanceof SymbolMacro)
506                     signal(new LispError(arg.writeToString() +
507                                          " has no dynamic value."));
508             }
509             return value;
510         }
511     };
512
513     // ### set
514
// set symbol value => value
515
private static final Primitive2 SET = new Primitive2("set", "symbol value")
516     {
517         public LispObject execute(LispObject first, LispObject second)
518             throws ConditionThrowable
519         {
520             Symbol symbol = checkSymbol(first);
521             Environment dynEnv =
522                 LispThread.currentThread().getDynamicEnvironment();
523             if (dynEnv != null) {
524                 Binding binding = dynEnv.getBinding(symbol);
525                 if (binding != null) {
526                     binding.value = second;
527                     return second;
528                 }
529             }
530             symbol.setSymbolValue(second);
531             return second;
532         }
533     };
534
535     // ### rplaca
536
private static final Primitive2 RPLACA =
537         new Primitive2("rplaca", "cons object")
538     {
539         public LispObject execute(LispObject first, LispObject second)
540             throws ConditionThrowable
541         {
542                 first.setCar(second);
543                 return first;
544         }
545     };
546
547     // ### rplacd
548
private static final Primitive2 RPLACD =
549         new Primitive2("rplacd", "cons object")
550     {
551         public LispObject execute(LispObject first, LispObject second)
552             throws ConditionThrowable
553         {
554                 first.setCdr(second);
555                 return first;
556         }
557     };
558
559     // ### +
560
private static final Primitive ADD = new Primitive("+", "&rest numbers")
561     {
562         public LispObject execute(LispObject first, LispObject second)
563             throws ConditionThrowable
564         {
565             return first.add(second);
566         }
567         public LispObject execute(LispObject[] args) throws ConditionThrowable
568         {
569             LispObject result = Fixnum.ZERO;
570             final int length = args.length;
571             for (int i = 0; i < length; i++)
572                 result = result.add(args[i]);
573             return result;
574         }
575     };
576
577     // ### 1+
578
private static final Primitive1 ONE_PLUS = new Primitive1("1+", "number")
579     {
580         public LispObject execute(LispObject arg) throws ConditionThrowable
581         {
582             return arg.incr();
583         }
584     };
585
586     // ### -
587
private static final Primitive SUBTRACT =
588         new Primitive("-", "minuend &rest subtrahends")
589     {
590         public LispObject execute(LispObject first, LispObject second)
591             throws ConditionThrowable
592         {
593             return first.subtract(second);
594         }
595         public LispObject execute(LispObject[] args) throws ConditionThrowable
596         {
597             switch (args.length) {
598                 case 0:
599                     signal(new WrongNumberOfArgumentsException("-"));
600                 case 1:
601                     return Fixnum.ZERO.subtract(args[0]);
602                 case 2:
603                     Debug.assertTrue(false);
604                     return args[0].subtract(args[1]);
605                 default: {
606                     LispObject result = args[0];
607                     for (int i = 1; i < args.length; i++)
608                         result = result.subtract(args[i]);
609                     return result;
610                 }
611             }
612         }
613     };
614
615     // ### 1-
616
private static final Primitive1 ONE_MINUS = new Primitive1("1-","number")
617     {
618         public LispObject execute(LispObject arg) throws ConditionThrowable
619         {
620             return arg.decr();
621         }
622     };
623
624     // ### when
625
private static final SpecialOperator WHEN = new SpecialOperator("when")
626     {
627         public LispObject execute(LispObject args, Environment env)
628             throws ConditionThrowable
629         {
630             if (args == NIL)
631                 signal(new WrongNumberOfArgumentsException(this));
632             final LispThread thread = LispThread.currentThread();
633             if (eval(args.car(), env, thread) != NIL) {
634                 args = args.cdr();
635                 LispObject result = NIL;
636                 while (args != NIL) {
637                     result = eval(args.car(), env, thread);
638                     args = args.cdr();
639                 }
640                 return result;
641             } else
642                 return thread.setValues(NIL);
643         }
644     };
645
646     // ### unless
647
private static final SpecialOperator UNLESS = new SpecialOperator("unless")
648     {
649         public LispObject execute(LispObject args, Environment env)
650             throws ConditionThrowable
651         {
652             if (args == NIL)
653                 signal(new WrongNumberOfArgumentsException(this));
654             final LispThread thread = LispThread.currentThread();
655             if (eval(args.car(), env, thread) == NIL) {
656                 args = args.cdr();
657                 LispObject result = NIL;
658                 while (args != NIL) {
659                     result = eval(args.car(), env, thread);
660                     args = args.cdr();
661                 }
662                 return result;
663             } else
664                 return thread.setValues(NIL);
665         }
666     };
667
668     // ### %output-object object stream => object
669
private static final Primitive2 _OUTPUT_OBJECT =
670         new Primitive2("%output-object", PACKAGE_SYS, false)
671     {
672         public LispObject execute(LispObject first, LispObject second)
673             throws ConditionThrowable
674         {
675             outSynonymOf(second)._writeString(first.writeToString());
676             return first;
677         }
678     };
679
680     // ### %write-to-string object => string
681
private static final Primitive1 _WRITE_TO_STRING =
682         new Primitive1("%write-to-string", PACKAGE_SYS, false)
683     {
684         public LispObject execute(LispObject arg) throws ConditionThrowable
685         {
686             return new SimpleString(arg.writeToString());
687         }
688     };
689
690     // ### princ-to-string
691
private static final Primitive1 PRINC_TO_STRING =
692         new Primitive1("princ-to-string", "object")
693     {
694         public LispObject execute(LispObject arg) throws ConditionThrowable
695         {
696             LispThread thread = LispThread.currentThread();
697             Environment oldDynEnv = thread.getDynamicEnvironment();
698             thread.bindSpecial(_PRINT_ESCAPE_, NIL);
699             thread.bindSpecial(_PRINT_READABLY_, NIL);
700             SimpleString string = new SimpleString(arg.writeToString());
701             thread.setDynamicEnvironment(oldDynEnv);
702             return string;
703         }
704     };
705
706     // ### prin1-to-string
707
private static final Primitive1 PRIN1_TO_STRING =
708         new Primitive1("prin1-to-string", "object")
709     {
710         public LispObject execute(LispObject arg) throws ConditionThrowable
711         {
712             LispThread thread = LispThread.currentThread();
713             Environment oldDynEnv = thread.getDynamicEnvironment();
714             thread.bindSpecial(_PRINT_ESCAPE_, T);
715             SimpleString string = new SimpleString(arg.writeToString());
716             thread.setDynamicEnvironment(oldDynEnv);
717             return string;
718         }
719     };
720
721     // ### %terpri
722
// %terpri output-stream => nil
723
private static final Primitive1 _TERPRI =
724         new Primitive1("%terpri", PACKAGE_SYS, false, "output-stream")
725     {
726         public LispObject execute(LispObject arg) throws ConditionThrowable
727         {
728             return outSynonymOf(arg).terpri();
729         }
730     };
731
732     // ### %fresh-line
733
// %fresh-line &optional output-stream => generalized-boolean
734
private static final Primitive1 _FRESH_LINE =
735         new Primitive1("%fresh-line", PACKAGE_SYS, false, "output-stream")
736     {
737         public LispObject execute(LispObject arg) throws ConditionThrowable
738         {
739             return outSynonymOf(arg).freshLine();
740         }
741     };
742
743     // ### boundp
744
// Determines only whether a symbol has a value in the global environment;
745
// any lexical bindings are ignored.
746
private static final Primitive1 BOUNDP = new Primitive1("boundp", "symbol")
747     {
748         public LispObject execute(LispObject obj) throws ConditionThrowable
749         {
750             Symbol symbol = checkSymbol(obj);
751             // PROGV: "If too few values are supplied, the remaining symbols
752
// are bound and then made to have no value." So BOUNDP must
753
// explicitly check for a binding with no value.
754
Environment dynEnv =
755                 LispThread.currentThread().getDynamicEnvironment();
756             if (dynEnv != null) {
757                 Binding binding = dynEnv.getBinding(symbol);
758                 if (binding != null)
759                     return binding.value != null ? T : NIL;
760             }
761             // No binding.
762
return symbol.getSymbolValue() != null ? T : NIL;
763         }
764     };
765
766     // ### fboundp
767
private static final Primitive1 FBOUNDP = new Primitive1("fboundp","name")
768     {
769         public LispObject execute(LispObject arg) throws ConditionThrowable
770         {
771             if (arg instanceof Symbol)
772                 return arg.getSymbolFunction() != null ? T : NIL;
773             if (arg instanceof Cons && arg.car() == Symbol.SETF) {
774                 LispObject f =
775                     get(checkSymbol(arg.cadr()), Symbol._SETF_FUNCTION);
776                 return f != null ? T : NIL;
777             }
778             signal(new TypeError(arg, "valid function name"));
779             return NIL;
780         }
781     };
782
783     // ### fmakunbound
784
private static final Primitive1 FMAKUNBOUND = new Primitive1("fmakunbound","name")
785     {
786         public LispObject execute(LispObject arg) throws ConditionThrowable
787         {
788             if (arg instanceof Symbol) {
789                 ((Symbol)arg).setSymbolFunction(null);
790             } else if (arg instanceof Cons && arg.car() == Symbol.SETF) {
791                 remprop(checkSymbol(arg.cadr()), Symbol._SETF_FUNCTION);
792             } else
793                 signal(new TypeError(arg, "valid function name"));
794             return arg;
795         }
796     };
797
798     // ### remprop
799
private static final Primitive2 REMPROP = new Primitive2("remprop","symbol indicator")
800     {
801         public LispObject execute(LispObject first, LispObject second)
802             throws ConditionThrowable
803         {
804             return remprop(checkSymbol(first), second);
805         }
806     };
807
808     // ### append
809
public static final Primitive APPEND = new Primitive("append","&rest lists") {
810         public LispObject execute()
811         {
812             return NIL;
813         }
814         public LispObject execute(LispObject arg)
815         {
816             return arg;
817         }
818         public LispObject execute(LispObject first, LispObject second)
819             throws ConditionThrowable
820         {
821             if (first == NIL)
822                 return second;
823             // APPEND is required to copy its first argument.
824
Cons result = new Cons(first.car());
825             Cons splice = result;
826             first = first.cdr();
827             while (first != NIL) {
828                 Cons temp = new Cons(first.car());
829                 splice.setCdr(temp);
830                 splice = temp;
831                 first = first.cdr();
832             }
833             splice.setCdr(second);
834             return result;
835         }
836         public LispObject execute(LispObject[] args) throws ConditionThrowable
837         {
838             Cons result = null;
839             Cons splice = null;
840             final int limit = args.length - 1;
841             int i;
842             for (i = 0; i < limit; i++) {
843                 LispObject top = args[i];
844                 if (top == NIL)
845                     continue;
846                 result = new Cons(top.car());
847                 splice = result;
848                 top = top.cdr();
849                 while (top != NIL) {
850                     Cons temp = new Cons(top.car());
851                     splice.setCdr(temp);
852                     splice = temp;
853                     top = top.cdr();
854                 }
855                 break;
856             }
857             if (result == null)
858                 return args[i];
859             for (++i; i < limit; i++) {
860                 LispObject top = args[i];
861                 while (top != NIL) {
862                     Cons temp = new Cons(top.car());
863                     splice.setCdr(temp);
864                     splice = temp;
865                     top = top.cdr();
866                 }
867             }
868             splice.setCdr(args[i]);
869             return result;
870         }
871     };
872
873     // ### nconc
874
private static final Primitive NCONC = new Primitive("nconc","&rest lists") {
875         public LispObject execute(LispObject[] array) throws ConditionThrowable
876         {
877             switch (array.length) {
878                 case 0:
879                     return NIL;
880                 case 1:
881                     return array[0];
882                 default: {
883                     LispObject result = null;
884                     LispObject splice = null;
885                     final int limit = array.length - 1;
886                     int i;
887                     for (i = 0; i < limit; i++) {
888                         LispObject list = array[i];
889                         if (list == NIL)
890                             continue;
891                         if (list instanceof Cons) {
892                             if (splice != null) {
893                                 splice.setCdr(list);
894                                 splice = list;
895                             }
896                             while (list instanceof Cons) {
897                                 if (result == null) {
898                                     result = list;
899                                     splice = result;
900                                 } else {
901                                     splice = list;
902                                 }
903                                 list = list.cdr();
904                             }
905                         } else
906                             signal(new TypeError(list, "list"));
907                     }
908                     if (result == null)
909                         return array[i];
910                     splice.setCdr(array[i]);
911                     return result;
912                 }
913             }
914         }
915     };
916
917     // ### =
918
// Numeric equality.
919
private static final Primitive EQUALS = new Primitive("=","&rest numbers") {
920         public LispObject execute(LispObject first, LispObject second)
921             throws ConditionThrowable
922         {
923             return first.isEqualTo(second) ? T : NIL;
924         }
925         public LispObject execute(LispObject[] array) throws ConditionThrowable
926         {
927             final int length = array.length;
928             if (length < 1)
929                 signal(new WrongNumberOfArgumentsException(this));
930             final LispObject obj = array[0];
931             for (int i = 1; i < length; i++) {
932                 if (array[i].isNotEqualTo(obj))
933                     return NIL;
934             }
935             return T;
936         }
937     };
938
939     // Returns true if no two numbers are the same; otherwise returns false.
940
private static final Primitive NOT_EQUALS =
941         new Primitive("/=", "&rest numbers")
942     {
943         public LispObject execute(LispObject first, LispObject second)
944             throws ConditionThrowable
945         {
946             return first.isNotEqualTo(second) ? T : NIL;
947         }
948         public LispObject execute(LispObject[] array) throws ConditionThrowable
949         {
950             final int length = array.length;
951             if (length == 2)
952                 return array[0].isNotEqualTo(array[1]) ? T : NIL;
953             if (length < 1)
954                 signal(new WrongNumberOfArgumentsException(this));
955             for (int i = 0; i < length; i++) {
956                 final LispObject obj = array[i];
957                 for (int j = i+1; j < length; j++) {
958                     if (array[j].isEqualTo(obj))
959                         return NIL;
960                 }
961             }
962             return T;
963         }
964     };
965
966     // ### <
967
// Numeric comparison.
968
private static final Primitive LESS_THAN = new Primitive("<","&rest numbers") {
969         public LispObject execute(LispObject first, LispObject second)
970             throws ConditionThrowable
971         {
972             return first.isLessThan(second) ? T : NIL;
973         }
974         public LispObject execute(LispObject[] array) throws ConditionThrowable
975         {
976             final int length = array.length;
977             if (length < 1)
978                 signal(new WrongNumberOfArgumentsException(this));
979             for (int i = 1; i < length; i++) {
980                 if (array[i].isLessThanOrEqualTo(array[i-1]))
981                     return NIL;
982             }
983             return T;
984         }
985     };
986
987     // ### <=
988
private static final Primitive LE = new Primitive("<=", "&rest numbers")
989     {
990         public LispObject execute(LispObject first, LispObject second)
991             throws ConditionThrowable
992         {
993             return first.isLessThanOrEqualTo(second) ? T : NIL;
994         }
995         public LispObject execute(LispObject[] array) throws ConditionThrowable
996         {
997             switch (array.length) {
998                 case 0:
999                     signal(new WrongNumberOfArgumentsException(this));
1000                case 1:
1001                    return T;
1002                case 2:
1003                    Debug.assertTrue(false);
1004                    return array[0].isLessThanOrEqualTo(array[1]) ? T : NIL;
1005                default: {
1006                    final int length = array.length;
1007                    for (int i = 1; i < length; i++) {
1008                        if (array[i].isLessThan(array[i-1]))
1009                            return NIL;
1010                    }
1011                    return T;
1012                }
1013            }
1014        }
1015    };
1016
1017    // ### >
1018
private static final Primitive GREATER_THAN =
1019        new Primitive(">", "&rest numbers")
1020    {
1021        public LispObject execute(LispObject first, LispObject second)
1022            throws ConditionThrowable
1023        {
1024            return first.isGreaterThan(second) ? T : NIL;
1025        }
1026        public LispObject execute(LispObject[] array) throws ConditionThrowable
1027        {
1028            final int length = array.length;
1029            if (length < 1)
1030                signal(new WrongNumberOfArgumentsException(this));
1031            for (int i = 1; i < length; i++) {
1032                if (array[i].isGreaterThanOrEqualTo(array[i-1]))
1033                    return NIL;
1034            }
1035            return T;
1036        }
1037    };
1038
1039    // ### >=
1040
private static final Primitive GE = new Primitive(">=", "&rest numbers")
1041    {
1042        public LispObject execute(LispObject first, LispObject second)
1043            throws ConditionThrowable
1044        {
1045            return first.isGreaterThanOrEqualTo(second) ? T : NIL;
1046        }
1047        public LispObject execute(LispObject[] array) throws ConditionThrowable
1048        {
1049            final int length = array.length;
1050            switch (length) {
1051                case 0:
1052                    signal(new WrongNumberOfArgumentsException(this));
1053                case 1:
1054                    return T;
1055                case 2:
1056                    Debug.assertTrue(false);
1057                    return array[0].isGreaterThanOrEqualTo(array[1]) ? T : NIL;
1058                default:
1059                    for (int i = 1; i < length; i++) {
1060                        if (array[i].isGreaterThan(array[i-1]))
1061                            return NIL;
1062                    }
1063                    return T;
1064            }
1065        }
1066    };
1067
1068    // ### assoc
1069
// assoc item alist &key key test test-not => entry
1070
// This is the bootstrap version (needed for %set-documentation).
1071
// Redefined properly in assoc.lisp.
1072
private static final Primitive ASSOC =
1073        new Primitive("assoc", "item alist &key key test test-not")
1074    {
1075        public LispObject execute(LispObject[] args) throws ConditionThrowable
1076        {
1077            if (args.length != 2)
1078                signal(new WrongNumberOfArgumentsException(this));
1079            LispObject item = args[0];
1080            LispObject alist = args[1];
1081            while (alist != NIL) {
1082                LispObject cons = alist.car();
1083                if (cons instanceof Cons) {
1084                    if (cons.car().eql(item))
1085                        return cons;
1086                } else if (cons != NIL)
1087                    signal(new TypeError(cons, "list"));
1088                alist = alist.cdr();
1089            }
1090            return NIL;
1091        }
1092    };
1093
1094    // ### nth
1095
// nth n list => object
1096
private static final Primitive2 NTH = new Primitive2("nth", "n list")
1097    {
1098        public LispObject execute(LispObject first, LispObject second)
1099            throws ConditionThrowable
1100        {
1101            int index = Fixnum.getValue(first);
1102            if (index < 0)
1103                signal(new TypeError("NTH: invalid index " + index + "."));
1104            int i = 0;
1105            while (true) {
1106                if (i == index)
1107                    return second.car();
1108                second = second.cdr();
1109                if (second == NIL)
1110                    return NIL;
1111                ++i;
1112            }
1113        }
1114    };
1115
1116    // ### %set-nth
1117
// %setnth n list new-object => new-object
1118
private static final Primitive3 _SET_NTH =
1119        new Primitive3("%set-nth", PACKAGE_SYS, false)
1120    {
1121        public LispObject execute(LispObject first, LispObject second,
1122                                  LispObject third)
1123            throws ConditionThrowable
1124        {
1125            int index = Fixnum.getValue(first);
1126            if (index < 0)
1127                signal(new TypeError("(SETF NTH): invalid index " + index + "."));
1128            int i = 0;
1129            while (true) {
1130                if (i == index) {
1131                    second.setCar(third);
1132                    return third;
1133                }
1134                second = second.cdr();
1135                if (second == NIL) {
1136                    return signal(new LispError("(SETF NTH): the index " +
1137                                                index + "is too large."));
1138                }
1139                ++i;
1140            }
1141        }
1142    };
1143
1144    // ### nthcdr
1145
private static final Primitive2 NTHCDR = new Primitive2("nthcdr", "n list")
1146    {
1147        public LispObject execute(LispObject first, LispObject second)
1148            throws ConditionThrowable
1149        {
1150            final int index = Fixnum.getValue(first);
1151            if (index < 0)
1152                signal(new TypeError("NTHCDR: invalid index " + index + "."));
1153            for (int i = 0; i < index; i++) {
1154                second = second.cdr();
1155                if (second == NIL)
1156                    return NIL;
1157            }
1158            return second;
1159        }
1160    };
1161
1162    // ### error
1163
private static final Primitive ERROR = new Primitive("error", "datum &rest arguments")
1164    {
1165        public LispObject execute(LispObject[] args) throws ConditionThrowable
1166        {
1167            if (args.length < 1) {
1168                signal(new WrongNumberOfArgumentsException(this));
1169                return NIL;
1170            }
1171            LispObject datum = args[0];
1172            if (datum instanceof Condition) {
1173                signal((Condition)datum);
1174                return NIL;
1175            }
1176            if (datum instanceof Symbol) {
1177                LispObject initArgs = NIL;
1178                for (int i = 1; i < args.length; i++)
1179                    initArgs = new Cons(args[i], initArgs);
1180                initArgs = initArgs.nreverse();
1181                Condition condition;
1182                if (datum == Symbol.FILE_ERROR)
1183                    condition = new FileError(initArgs);
1184                else if (datum == Symbol.PACKAGE_ERROR)
1185                    condition = new PackageError(initArgs);
1186                else if (datum == Symbol.PARSE_ERROR)
1187                    condition = new ParseError(initArgs);
1188                else if (datum == Symbol.PROGRAM_ERROR)
1189                    condition = new ProgramError(initArgs);
1190                else if (datum == Symbol.SIMPLE_CONDITION)
1191                    condition = new SimpleCondition(initArgs);
1192                else if (datum == Symbol.SIMPLE_WARNING)
1193                    condition = new SimpleWarning(initArgs);
1194                else if (datum == Symbol.UNBOUND_SLOT)
1195                    condition = new UnboundSlot(initArgs);
1196                else if (datum == Symbol.WARNING)
1197                    condition = new Warning(initArgs);
1198                else if (datum == Symbol.SIMPLE_ERROR)
1199                    condition = new SimpleError(initArgs);
1200                else if (datum == Symbol.SIMPLE_TYPE_ERROR)
1201                    condition = new SimpleTypeError(initArgs);
1202                else if (datum == Symbol.CONTROL_ERROR)
1203                    condition = new ControlError(initArgs);
1204                else if (datum == Symbol.TYPE_ERROR)
1205                    condition = new TypeError(initArgs);
1206                else if (datum == Symbol.UNDEFINED_FUNCTION)
1207                    condition = new UndefinedFunction(initArgs);
1208                else
1209                    // Default.
1210
condition = new SimpleError(initArgs);
1211                signal(condition);
1212                return NIL;
1213            }
1214            // Default is SIMPLE-ERROR.
1215
LispObject formatControl = args[0];
1216            LispObject formatArguments = NIL;
1217            for (int i = 1; i < args.length; i++)
1218                formatArguments = new Cons(args[i], formatArguments);
1219            formatArguments = formatArguments.nreverse();
1220            signal(new SimpleError(formatControl, formatArguments));
1221            return NIL;
1222        }
1223    };
1224
1225    // ### signal
1226
private static final Primitive SIGNAL =
1227        new Primitive("signal", "datum &rest arguments")
1228    {
1229        public LispObject execute(LispObject[] args) throws ConditionThrowable
1230        {
1231            if (args.length < 1)
1232                throw new ConditionThrowable(new WrongNumberOfArgumentsException(this));
1233            if (args[0] instanceof Condition)
1234                throw new ConditionThrowable((Condition)args[0]);
1235            throw new ConditionThrowable (new SimpleCondition());
1236        }
1237    };
1238
1239    // ### %format
1240
private static final Primitive _FORMAT =
1241        new Primitive("%format", PACKAGE_SYS, false,
1242                      "destination control-string &rest args")
1243    {
1244        public LispObject execute(LispObject[] args) throws ConditionThrowable
1245        {
1246            if (args.length < 2)
1247                signal(new WrongNumberOfArgumentsException(this));
1248            LispObject destination = args[0];
1249            // Copy remaining arguments.
1250
LispObject[] _args = new LispObject[args.length-1];
1251            for (int i = 0; i < _args.length; i++)
1252                _args[i] = args[i+1];
1253            String JavaDoc s = _format(_args);
1254            if (destination == T) {
1255                checkCharacterOutputStream(_STANDARD_OUTPUT_.symbolValue())._writeString(s);
1256                return NIL;
1257            }
1258            if (destination == NIL)
1259                return new SimpleString(s);
1260            if (destination instanceof TwoWayStream) {
1261                Stream out = ((TwoWayStream)destination).getOutputStream();
1262                if (out instanceof Stream) {
1263                    ((Stream)out)._writeString(s);
1264                    return NIL;
1265                }
1266                signal(new TypeError(destination, "character output stream"));
1267            }
1268            if (destination instanceof Stream) {
1269                ((Stream)destination)._writeString(s);
1270                return NIL;
1271            }
1272            return NIL;
1273        }
1274    };
1275
1276    private static final String JavaDoc _format(LispObject[] args) throws ConditionThrowable
1277    {
1278        LispObject formatControl = args[0];
1279        LispObject formatArguments = NIL;
1280        for (int i = 1; i < args.length; i++)
1281            formatArguments = new Cons(args[i], formatArguments);
1282        formatArguments = formatArguments.nreverse();
1283        return format(formatControl, formatArguments);
1284    }
1285
1286    private static final Symbol _SIMPLE_FORMAT_FUNCTION_ =
1287        internSpecial("*SIMPLE-FORMAT-FUNCTION*", PACKAGE_SYS, _FORMAT);
1288
1289    // ### %defun
1290
// %defun name arglist body &optional environment => name
1291
private static final Primitive _DEFUN =
1292        new Primitive("%defun", PACKAGE_SYS, false,
1293                      "function-name lambda-list body &optional environment")
1294    {
1295        public LispObject execute(LispObject first, LispObject second,
1296                                  LispObject third)
1297            throws ConditionThrowable
1298        {
1299            return execute(first, second, third, new Environment());
1300        }
1301
1302        public LispObject execute(LispObject first, LispObject second,
1303                                  LispObject third, LispObject fourth)
1304            throws ConditionThrowable
1305        {
1306            Environment env;
1307            if (fourth != NIL)
1308                env = checkEnvironment(fourth);
1309            else
1310                env = new Environment();
1311            final Symbol symbol;
1312            if (first instanceof Symbol) {
1313                symbol = (Symbol) first;
1314                if (symbol.getSymbolFunction() instanceof SpecialOperator) {
1315                    String JavaDoc message =
1316                        symbol.getName() + " is a special operator and may not be redefined.";
1317                    return signal(new ProgramError(message));
1318                }
1319            } else if (first instanceof Cons && first.car() == Symbol.SETF) {
1320                symbol = checkSymbol(first.cadr());
1321            } else
1322                return signal(new TypeError(first.writeToString() +
1323                                            " is not a valid function name."));
1324            LispObject arglist = checkList(second);
1325            LispObject body = checkList(third);
1326            if (body.car() instanceof AbstractString && body.cdr() != NIL) {
1327                // Documentation.
1328
if (first instanceof Symbol)
1329                    symbol.setFunctionDocumentation(body.car());
1330                else
1331                    ; // FIXME Support documentation for SETF functions!
1332
body = body.cdr();
1333            }
1334            LispObject decls = NIL;
1335            while (body.car() instanceof Cons && body.car().car() == Symbol.DECLARE) {
1336                decls = new Cons(body.car(), decls);
1337                body = body.cdr();
1338            }
1339            body = new Cons(symbol, body);
1340            body = new Cons(Symbol.BLOCK, body);
1341            body = new Cons(body, NIL);
1342            while (decls != NIL) {
1343                body = new Cons(decls.car(), body);
1344                decls = decls.cdr();
1345            }
1346            Closure closure = new Closure(first instanceof Symbol ? symbol : null,
1347                                          arglist, body, env);
1348            closure.setArglist(arglist);
1349            if (first instanceof Symbol) {
1350                symbol.setSymbolFunction(closure);
1351            } else {
1352                // SETF function
1353
put(symbol, Symbol._SETF_FUNCTION, closure);
1354            }
1355            // Clear function table entry (if any).
1356
if (FUNCTION_TABLE != null) {
1357                FUNCTION_TABLE.remhash(first);
1358            }
1359            return first;
1360        }
1361    };
1362
1363    // ### macro-function
1364
// Need to support optional second argument specifying environment.
1365
private static final Primitive MACRO_FUNCTION =
1366        new Primitive("macro-function", "symbol &optional environment")
1367    {
1368        public LispObject execute(LispObject arg) throws ConditionThrowable
1369        {
1370            LispObject obj = arg.getSymbolFunction();
1371            if (obj instanceof AutoloadMacro) {
1372                ((AutoloadMacro)obj).load();
1373                obj = arg.getSymbolFunction();
1374            }
1375            if (obj instanceof MacroObject)
1376                return ((MacroObject)obj).getExpander();
1377            if (obj instanceof SpecialOperator) {
1378                obj = get((Symbol) arg, Symbol.MACROEXPAND_MACRO, NIL);
1379                if (obj instanceof AutoloadMacro) {
1380                    ((AutoloadMacro)obj).load();
1381                    obj = get((Symbol) arg, Symbol.MACROEXPAND_MACRO, NIL);
1382                }
1383                if (obj instanceof MacroObject)
1384                    return ((MacroObject)obj).getExpander();
1385            }
1386            return NIL;
1387        }
1388    };
1389
1390    // ### defmacro
1391
private static final SpecialOperator DEFMACRO = new SpecialOperator("defmacro")
1392    {
1393        public LispObject execute(LispObject args, Environment env)
1394            throws ConditionThrowable
1395        {
1396            Symbol symbol = checkSymbol(args.car());
1397            LispObject lambdaList = checkList(args.cadr());
1398            LispObject body = args.cddr();
1399            LispObject block = new Cons(Symbol.BLOCK, new Cons(symbol, body));
1400            LispObject toBeApplied =
1401                list2(Symbol.FUNCTION, list3(Symbol.LAMBDA, lambdaList, block));
1402            LispObject formArg = gensym("FORM-");
1403            LispObject envArg = gensym("ENV-"); // Ignored.
1404
LispObject expander =
1405                list3(Symbol.LAMBDA, list2(formArg, envArg),
1406                      list3(Symbol.APPLY, toBeApplied,
1407                            list2(Symbol.CDR, formArg)));
1408            Closure expansionFunction =
1409                new Closure(expander.cadr(), expander.cddr(), env);
1410            MacroObject macroObject = new MacroObject(expansionFunction);
1411            if (symbol.getSymbolFunction() instanceof SpecialOperator)
1412                put(symbol, Symbol.MACROEXPAND_MACRO, macroObject);
1413            else
1414                symbol.setSymbolFunction(macroObject);
1415        macroObject.setArglist(lambdaList);
1416            LispThread.currentThread().clearValues();
1417            return symbol;
1418        }
1419    };
1420
1421    // ### make-macro
1422
private static final Primitive1 MAKE_MACRO =
1423        new Primitive1("make-macro", PACKAGE_SYS, false)
1424    {
1425        public LispObject execute(LispObject arg) throws ConditionThrowable
1426        {
1427            return new MacroObject(arg);
1428        }
1429    };
1430
1431    // ### %defparameter
1432
private static final Primitive3 _DEFPARAMETER =
1433        new Primitive3("%defparameter", PACKAGE_SYS, false)
1434    {
1435        public LispObject execute(LispObject first, LispObject second,
1436                                  LispObject third)
1437            throws ConditionThrowable
1438        {
1439            Symbol symbol = checkSymbol(first);
1440            if (third instanceof AbstractString)
1441                symbol.setVariableDocumentation(third);
1442            else if (third != NIL)
1443                signal(new TypeError(third, "string"));
1444            symbol.setSymbolValue(second);
1445            symbol.setSpecial(true);
1446            return symbol;
1447        }
1448    };
1449
1450    // ### %defvar
1451
private static final Primitive1 _DEFVAR =
1452        new Primitive1("%defvar", PACKAGE_SYS, false)
1453    {
1454        public LispObject execute(LispObject arg) throws ConditionThrowable
1455        {
1456            Symbol symbol = checkSymbol(arg);
1457            symbol.setSpecial(true);
1458            return symbol;
1459        }
1460    };
1461
1462    // ### %defconstant
1463
private static final Primitive3 _DEFCONSTANT =
1464        new Primitive3("%defconstant", PACKAGE_SYS, false)
1465    {
1466        public LispObject execute(LispObject first, LispObject second,
1467                                  LispObject third)
1468            throws ConditionThrowable
1469        {
1470            Symbol symbol = checkSymbol(first);
1471            if (third instanceof AbstractString)
1472                symbol.setVariableDocumentation(third);
1473            else if (third != NIL)
1474                signal(new TypeError(third, "string"));
1475            symbol.setSymbolValue(second);
1476            symbol.setSpecial(true);
1477            symbol.setConstant(true);
1478            return symbol;
1479        }
1480    };
1481
1482    // ### cond
1483
private static final SpecialOperator COND = new SpecialOperator("cond", "&rest clauses") {
1484        public LispObject execute(LispObject args, Environment env)
1485            throws ConditionThrowable
1486        {
1487            final LispThread thread = LispThread.currentThread();
1488            LispObject result = NIL;
1489            while (args != NIL) {
1490                LispObject clause = args.car();
1491                result = eval(clause.car(), env, thread);
1492                thread.clearValues();
1493                if (result != NIL) {
1494                    LispObject body = clause.cdr();
1495                    while (body != NIL) {
1496                        result = eval(body.car(), env, thread);
1497                        body = body.cdr();
1498                    }
1499                    return result;
1500                }
1501                args = args.cdr();
1502            }
1503            return result;
1504        }
1505    };
1506
1507    // ### case
1508
private static final SpecialOperator CASE = new SpecialOperator("case", "keyform &body cases")
1509    {
1510        public LispObject execute(LispObject args, Environment env)
1511            throws ConditionThrowable
1512        {
1513            final LispThread thread = LispThread.currentThread();
1514            LispObject key = eval(args.car(), env, thread);
1515            args = args.cdr();
1516            while (args != NIL) {
1517                LispObject clause = args.car();
1518                LispObject keys = clause.car();
1519                boolean match = false;
1520                if (keys.listp()) {
1521                    while (keys != NIL) {
1522                        LispObject candidate = keys.car();
1523                        if (key.eql(candidate)) {
1524                            match = true;
1525                            break;
1526                        }
1527                        keys = keys.cdr();
1528                    }
1529                } else {
1530                    LispObject candidate = keys;
1531                    if (candidate == T || candidate == Symbol.OTHERWISE)
1532                        match = true;
1533                    else if (key.eql(candidate))
1534                        match = true;
1535                }
1536                if (match) {
1537                    return progn(clause.cdr(), env, thread);
1538                }
1539                args = args.cdr();
1540            }
1541            return NIL;
1542        }
1543    };
1544
1545    // ### ecase
1546
private static final SpecialOperator ECASE = new SpecialOperator("ecase", "keyform &body cases")
1547    {
1548        public LispObject execute(LispObject args, Environment env)
1549            throws ConditionThrowable
1550        {
1551            final LispThread thread = LispThread.currentThread();
1552            LispObject key = eval(args.car(), env, thread);
1553            args = args.cdr();
1554            while (args != NIL) {
1555                LispObject clause = args.car();
1556                LispObject keys = clause.car();
1557                boolean match = false;
1558                if (keys.listp()) {
1559                    while (keys != NIL) {
1560                        LispObject candidate = keys.car();
1561                        if (key.eql(candidate)) {
1562                            match = true;
1563                            break;
1564                        }
1565                        keys = keys.cdr();
1566                    }
1567                } else {
1568                    LispObject candidate = keys;
1569                    if (key.eql(candidate))
1570                        match = true;
1571                }
1572                if (match) {
1573                    return progn(clause.cdr(), env, thread);
1574                }
1575                args = args.cdr();
1576            }
1577            signal(new TypeError("ECASE: no match for " + key));
1578            return NIL;
1579        }
1580    };
1581
1582    // ### upgraded-array-element-type
1583
// upgraded-array-element-type typespec &optional environment
1584
// => upgraded-typespec
1585
private static final Primitive UPGRADED_ARRAY_ELEMENT_TYPE =
1586        new Primitive("upgraded-array-element-type", "typespec &optional environment") {
1587        public LispObject execute(LispObject arg) throws ConditionThrowable
1588        {
1589            return getUpgradedArrayElementType(arg);
1590        }
1591        public LispObject execute(LispObject first, LispObject second)
1592            throws ConditionThrowable
1593        {
1594            // Ignore environment.
1595
return getUpgradedArrayElementType(first);
1596        }
1597    };
1598
1599    // ### array-rank
1600
// array-rank array => rank
1601
private static final Primitive1 ARRAY_RANK =
1602        new Primitive1("array-rank", "array") {
1603        public LispObject execute(LispObject arg) throws ConditionThrowable
1604        {
1605            return new Fixnum(checkArray(arg).getRank());
1606        }
1607    };
1608
1609    // ### array-dimensions
1610
// array-dimensions array => dimensions
1611
// Returns a list of integers. Fill pointer (if any) is ignored.
1612
private static final Primitive1 ARRAY_DIMENSIONS =
1613        new Primitive1("array-dimensions", "array") {
1614        public LispObject execute(LispObject arg) throws ConditionThrowable
1615        {
1616            return checkArray(arg).getDimensions();
1617        }
1618    };
1619
1620    // ### array-dimension
1621
// array-dimension array axis-number => dimension
1622
private static final Primitive2 ARRAY_DIMENSION =
1623        new Primitive2("array-dimension", "array axis-number") {
1624        public LispObject execute(LispObject first, LispObject second)
1625            throws ConditionThrowable
1626        {
1627            return new Fixnum(checkArray(first).getDimension(Fixnum.getValue(second)));
1628        }
1629    };
1630
1631    // ### array-total-size
1632
// array-total-size array => size
1633
private static final Primitive1 ARRAY_TOTAL_SIZE =
1634        new Primitive1("array-total-size","array") {
1635        public LispObject execute(LispObject arg) throws ConditionThrowable
1636        {
1637            return new Fixnum(checkArray(arg).getTotalSize());
1638        }
1639    };
1640
1641
1642    // ### array-element-type
1643
// array-element-type array => typespec
1644
private static final Primitive1 ARRAY_ELEMENT_TYPE =
1645        new Primitive1("array-element-type", "array")
1646    {
1647        public LispObject execute(LispObject arg) throws ConditionThrowable
1648        {
1649            return checkArray(arg).getElementType();
1650        }
1651    };
1652
1653    // ### adjustable-array-p
1654
private static final Primitive1 ADJUSTABLE_ARRAY_P =
1655        new Primitive1("adjustable-array-p", "array")
1656    {
1657        public LispObject execute(LispObject arg) throws ConditionThrowable
1658        {
1659            try {
1660                return ((AbstractArray)arg).isAdjustable() ? T : NIL;
1661            }
1662            catch (ClassCastException JavaDoc e) {
1663                return signal(new TypeError(arg, Symbol.ARRAY));
1664            }
1665        }
1666    };
1667
1668    // ### array-displacement
1669
// array-displacement array => displaced-to, displaced-index-offset
1670
private static final Primitive1 ARRAY_DISPLACEMENT =
1671        new Primitive1("array-displacement", "array")
1672    {
1673        public LispObject execute(LispObject arg) throws ConditionThrowable
1674        {
1675            return checkArray(arg).arrayDisplacement();
1676        }
1677    };
1678
1679    // ### array-in-bounds-p
1680
// array-in-bounds-p array &rest subscripts => generalized-boolean
1681
private static final Primitive ARRAY_IN_BOUNDS_P =
1682        new Primitive("array-in-bounds-p", "array &rest subscripts")
1683    {
1684        public LispObject execute(LispObject[] args) throws ConditionThrowable
1685        {
1686            if (args.length < 1)
1687                signal(new WrongNumberOfArgumentsException(this));
1688            AbstractArray array = checkArray(args[0]);
1689            int rank = array.getRank();
1690            if (rank != args.length - 1) {
1691                StringBuffer JavaDoc sb = new StringBuffer JavaDoc("ARRAY-IN-BOUNDS-P: ");
1692                sb.append("wrong number of subscripts (");
1693                sb.append(args.length - 1);
1694                sb.append(") for array of rank ");
1695                sb.append(rank);
1696                signal(new ProgramError(sb.toString()));
1697            }
1698            for (int i = 0; i < rank; i++) {
1699                LispObject arg = args[i+1];
1700                if (arg instanceof Fixnum) {
1701                    int subscript = ((Fixnum)arg).getValue();
1702                    if (subscript < 0 || subscript >= array.getDimension(i))
1703                        return NIL;
1704                } else if (arg instanceof Bignum) {
1705                    return NIL;
1706                } else
1707                    signal(new TypeError(arg, "integer"));
1708            }
1709            return T;
1710        }
1711    };
1712
1713    // ### %array-row-major-index
1714
// %array-row-major-index array subscripts => index
1715
private static final Primitive2 _ARRAY_ROW_MAJOR_INDEX =
1716        new Primitive2("%array-row-major-index", PACKAGE_SYS, false)
1717    {
1718        public LispObject execute(LispObject first, LispObject second)
1719            throws ConditionThrowable
1720        {
1721            AbstractArray array = checkArray(first);
1722            LispObject[] subscripts = second.copyToArray();
1723            return number(array.getRowMajorIndex(subscripts));
1724        }
1725    };
1726
1727    // ### aref
1728
// aref array &rest subscripts => element
1729
private static final Primitive AREF =
1730        new Primitive("aref", "array &rest subscripts")
1731    {
1732        public LispObject execute() throws ConditionThrowable
1733        {
1734            return signal(new WrongNumberOfArgumentsException(this));
1735        }
1736
1737        public LispObject execute(LispObject arg) throws ConditionThrowable
1738        {
1739            AbstractArray array = checkArray(arg);
1740            if (array.getRank() == 0)
1741                return array.getRowMajor(0);
1742            StringBuffer JavaDoc sb =
1743                new StringBuffer JavaDoc("Wrong number of subscripts (0) for array of rank ");
1744            sb.append(array.getRank());
1745            sb.append('.');
1746            signal(new ProgramError(sb.toString()));
1747            return NIL;
1748        }
1749
1750        public LispObject execute(LispObject first, LispObject second)
1751            throws ConditionThrowable
1752        {
1753            return first.AREF(second);
1754        }
1755
1756        public LispObject execute(LispObject first, LispObject second,
1757                                  LispObject third)
1758            throws ConditionThrowable
1759        {
1760            final AbstractArray array;
1761            try {
1762                array = checkArray(first);
1763            }
1764            catch (ClassCastException JavaDoc e) {
1765                return signal(new TypeError(first, Symbol.ARRAY));
1766            }
1767            final int[] subs = new int[2];
1768            try {
1769                subs[0] = ((Fixnum)second).value;
1770            }
1771            catch (ClassCastException JavaDoc e) {
1772                return signal(new TypeError(second, Symbol.FIXNUM));
1773            }
1774            try {
1775                subs[1] = ((Fixnum)third).value;
1776            }
1777            catch (ClassCastException JavaDoc e) {
1778                return signal(new TypeError(third, Symbol.FIXNUM));
1779            }
1780            return array.get(subs);
1781        }
1782
1783        public LispObject execute(LispObject[] args) throws ConditionThrowable
1784        {
1785            final AbstractArray array;
1786            try {
1787                array = checkArray(args[0]);
1788            }
1789            catch (ClassCastException JavaDoc e) {
1790                return signal(new TypeError(args[0], Symbol.ARRAY));
1791            }
1792            final int[] subs = new int[args.length - 1];
1793            for (int i = subs.length; i-- > 0;) {
1794                try {
1795                    subs[i] = ((Fixnum)args[i+1]).value;
1796                }
1797                catch (ClassCastException JavaDoc e) {
1798                    return signal(new TypeError(args[i+i], Symbol.FIXNUM));
1799                }
1800            }
1801            return array.get(subs);
1802        }
1803    };
1804
1805    // ### %aset
1806
// %aset array subscripts new-element => new-element
1807
private static final Primitive _ASET =
1808        new Primitive("%aset", PACKAGE_SYS, false, "array subscripts new-element")
1809    {
1810        public LispObject execute() throws ConditionThrowable
1811        {
1812            return signal(new WrongNumberOfArgumentsException(this));
1813        }
1814
1815        public LispObject execute(LispObject arg) throws ConditionThrowable
1816        {
1817            return signal(new WrongNumberOfArgumentsException(this));
1818        }
1819
1820        public LispObject execute(LispObject first, LispObject second)
1821            throws ConditionThrowable
1822        {
1823            // Rank zero array.
1824
final ZeroRankArray array;
1825            try {
1826                array = (ZeroRankArray) first;
1827            }
1828            catch (ClassCastException JavaDoc e) {
1829                return signal(new TypeError(first + " is not an array of rank 0."));
1830            }
1831            array.setRowMajor(0, second);
1832            return second;
1833        }
1834
1835        public LispObject execute(LispObject first, LispObject second,
1836                                  LispObject third)
1837            throws ConditionThrowable
1838        {
1839            final AbstractVector v;
1840            try {
1841                v = (AbstractVector) first;
1842            }
1843            catch (ClassCastException JavaDoc e) {
1844                return signal(new TypeError(first, Symbol.VECTOR));
1845            }
1846            final int index;
1847            try {
1848                index = ((Fixnum)second).value;
1849            }
1850            catch (ClassCastException JavaDoc e) {
1851                return signal(new TypeError(second, Symbol.FIXNUM));
1852            }
1853            v.setRowMajor(index, third);
1854            return third;
1855        }
1856
1857        public LispObject execute(LispObject[] args) throws ConditionThrowable
1858        {
1859            final AbstractArray array;
1860            try {
1861                array = (AbstractArray) args[0];
1862            }
1863            catch (ClassCastException JavaDoc e) {
1864                return signal(new TypeError(args[0], Symbol.ARRAY));
1865            }
1866            final int nsubs = args.length - 2;
1867            final int[] subs = new int[nsubs];
1868            for (int i = nsubs; i-- > 0;) {
1869                try {
1870                    subs[i] = ((Fixnum)args[i+1]).value;
1871                }
1872                catch (ClassCastException JavaDoc e) {
1873                    signal(new TypeError(args[i+1], Symbol.FIXNUM));
1874                }
1875            }
1876            final LispObject newValue = args[args.length - 1];
1877            array.set(subs, newValue);
1878            return newValue;
1879        }
1880    };
1881
1882    // ### row-major-aref
1883
// row-major-aref array index => element
1884
private static final Primitive2 ROW_MAJOR_AREF =
1885        new Primitive2("row-major-aref", "array index")
1886    {
1887        public LispObject execute(LispObject first, LispObject second)
1888            throws ConditionThrowable
1889        {
1890            try {
1891                return ((AbstractArray)first).getRowMajor(((Fixnum)second).value);
1892            }
1893            catch (ClassCastException JavaDoc e) {
1894                if (first instanceof AbstractArray)
1895                    return signal(new TypeError(second, Symbol.FIXNUM));
1896                else
1897                    return signal(new TypeError(first, Symbol.ARRAY));
1898            }
1899        }
1900    };
1901
1902    // ### %set-row-major-aref
1903
// %set-row-major-aref array index new-value => new-value
1904
private static final Primitive3 _SET_ROW_MAJOR_AREF =
1905        new Primitive3("%set-row-major-aref", PACKAGE_SYS, false)
1906    {
1907        public LispObject execute(LispObject first, LispObject second,
1908                                  LispObject third)
1909            throws ConditionThrowable
1910        {
1911            try {
1912                ((AbstractArray)first).setRowMajor(((Fixnum)second).value, third);
1913                return third;
1914            }
1915            catch (ClassCastException JavaDoc e) {
1916                if (first instanceof AbstractArray)
1917                    return signal(new TypeError(second, Symbol.FIXNUM));
1918                else
1919                    return signal(new TypeError(first, Symbol.ARRAY));
1920            }
1921        }
1922    };
1923
1924    // ### vector
1925
private static final Primitive VECTOR = new Primitive("vector", "&rest objects")
1926    {
1927        public LispObject execute(LispObject[] args) throws ConditionThrowable
1928        {
1929            return new SimpleVector(args);
1930        }
1931    };
1932
1933    // ### %vset
1934
// %vset vector index new-value => new-value
1935
private static final Primitive3 _VSET =
1936        new Primitive3("%vset", PACKAGE_SYS, false)
1937    {
1938        public LispObject execute(LispObject first, LispObject second,
1939                                  LispObject third)
1940            throws ConditionThrowable
1941        {
1942            try {
1943                ((AbstractVector)first).setRowMajor(((Fixnum)second).value, third);
1944                return third;
1945            }
1946            catch (ClassCastException JavaDoc e) {
1947                if (first instanceof AbstractVector)
1948                    return signal(new TypeError(second, Symbol.FIXNUM));
1949                else
1950                    return signal(new TypeError(first, Symbol.VECTOR));
1951            }
1952        }
1953    };
1954
1955    // ### fill-pointer
1956
private static final Primitive1 FILL_POINTER =
1957        new Primitive1("fill-pointer", "vector")
1958    {
1959        public LispObject execute(LispObject arg)
1960            throws ConditionThrowable
1961        {
1962            try {
1963                return new Fixnum(((AbstractArray)arg).getFillPointer());
1964            }
1965            catch (ClassCastException JavaDoc e) {
1966                return signal(new TypeError(arg, Symbol.ARRAY));
1967            }
1968        }
1969    };
1970
1971    // ### %set-fill-pointer vector new-fill-pointer
1972
private static final Primitive2 _SET_FILL_POINTER =
1973        new Primitive2("%set-fill-pointer", PACKAGE_SYS, false) {
1974        public LispObject execute(LispObject first, LispObject second)
1975            throws ConditionThrowable
1976        {
1977            try {
1978                AbstractVector v = (AbstractVector) first;
1979                if (v.hasFillPointer())
1980                    v.setFillPointer(second);
1981                else
1982                    v.noFillPointer();
1983                return second;
1984            }
1985            catch (ClassCastException JavaDoc e) {
1986                return signal(new TypeError(first, Symbol.VECTOR));
1987            }
1988        }
1989    };
1990
1991    // ### vector-push new-element vector => index-of-new-element
1992
private static final Primitive2 VECTOR_PUSH =
1993        new Primitive2("vector-push","new-element vector")
1994    {
1995        public LispObject execute(LispObject first, LispObject second)
1996            throws ConditionThrowable
1997        {
1998            AbstractVector v = checkVector(second);
1999            int fillPointer = v.getFillPointer();
2000            if (fillPointer < 0)
2001                v.noFillPointer();
2002            if (fillPointer >= v.capacity())
2003                return NIL;
2004            v.setRowMajor(fillPointer, first);
2005            v.setFillPointer(fillPointer + 1);
2006            return new Fixnum(fillPointer);
2007        }
2008    };
2009
2010    // ### vector-push-extend new-element vector &optional extension
2011
// => index-of-new-element
2012
private static final Primitive VECTOR_PUSH_EXTEND =
2013        new Primitive("vector-push-extend",
2014                      "new-element vector &optional extension")
2015    {
2016        public LispObject execute(LispObject first, LispObject second)
2017            throws ConditionThrowable
2018        {
2019            try {
2020                return ((AbstractVector)second).vectorPushExtend(first);
2021            }
2022            catch (ClassCastException JavaDoc e) {
2023                return signal(new TypeError(second, Symbol.VECTOR));
2024            }
2025        }
2026
2027        public LispObject execute(LispObject first, LispObject second,
2028                                  LispObject third)
2029            throws ConditionThrowable
2030        {
2031            try {
2032                return ((AbstractVector)second).vectorPushExtend(first, third);
2033            }
2034            catch (ClassCastException JavaDoc e) {
2035                return signal(new TypeError(second, Symbol.VECTOR));
2036            }
2037        }
2038    };
2039
2040    // ### vector-pop vector => element
2041
private static final Primitive1 VECTOR_POP =
2042        new Primitive1("vector-pop", "vector")
2043    {
2044        public LispObject execute(LispObject arg) throws ConditionThrowable
2045        {
2046            AbstractVector v = checkVector(arg);
2047            int fillPointer = v.getFillPointer();
2048            if (fillPointer < 0)
2049                v.noFillPointer();
2050            if (fillPointer == 0)
2051                signal(new LispError("nothing left to pop"));
2052            int newFillPointer = v.checkIndex(fillPointer - 1);
2053            LispObject element = v.getRowMajor(newFillPointer);
2054            v.setFillPointer(newFillPointer);
2055            return element;
2056        }
2057    };
2058
2059    // ### type-of
2060
private static final Primitive1 TYPE_OF = new Primitive1("type-of", "object")
2061    {
2062        public LispObject execute(LispObject arg) throws ConditionThrowable
2063        {
2064            return arg.typeOf();
2065        }
2066    };
2067
2068    // ### class-of
2069
private static final Primitive1 CLASS_OF = new Primitive1("class-of", "object")
2070    {
2071        public LispObject execute(LispObject arg) throws ConditionThrowable
2072        {
2073            return arg.classOf();
2074        }
2075    };
2076
2077    // ### simple-typep
2078
private static final Primitive2 SIMPLE_TYPEP =
2079        new Primitive2("simple-typep", PACKAGE_SYS, false)
2080    {
2081        public LispObject execute(LispObject first, LispObject second)
2082            throws ConditionThrowable
2083        {
2084            return first.typep(second);
2085        }
2086    };
2087
2088    // ### function-lambda-expression
2089
// function-lambda-expression function => lambda-expression, closure-p, name
2090
private static final Primitive1 FUNCTION_LAMBDA_EXPRESSION =
2091        new Primitive1("function-lambda-expression", "function")
2092    {
2093        public LispObject execute(LispObject arg) throws ConditionThrowable
2094        {
2095            final LispObject value1, value2;
2096            Function function = checkFunction(arg);
2097            String JavaDoc name = function.getName();
2098            final LispObject value3 = name != null ? new SimpleString(name) : NIL;
2099            if (function instanceof CompiledClosure) {
2100                value1 = NIL;
2101                value2 = T;
2102            } else if (function instanceof Closure && !(function instanceof CompiledFunction)) {
2103                Closure closure = (Closure) function;
2104                LispObject expr = closure.getBody();
2105                expr = new Cons(closure.getParameterList(), expr);
2106                expr = new Cons(Symbol.LAMBDA, expr);
2107                value1 = expr;
2108                Environment env = closure.getEnvironment();
2109                if (env == null || env.isEmpty())
2110                    value2 = NIL;
2111                else
2112                    value2 = env; // Return environment as closure-p.
2113
} else
2114                value1 = value2 = NIL;
2115            return LispThread.currentThread().setValues(value1, value2, value3);
2116        }
2117    };
2118
2119    // ### funcall
2120
// This needs to be public for LispAPI.java.
2121
public static final Primitive FUNCALL =
2122        new Primitive("funcall", "function &rest args")
2123    {
2124        public LispObject execute(LispObject arg) throws ConditionThrowable
2125        {
2126            return funcall0(requireFunction(arg), LispThread.currentThread());
2127        }
2128        public LispObject execute(LispObject first, LispObject second)
2129            throws ConditionThrowable
2130        {
2131            return funcall1(requireFunction(first), second,
2132                            LispThread.currentThread());
2133        }
2134        public LispObject execute(LispObject first, LispObject second,
2135                                  LispObject third)
2136            throws ConditionThrowable
2137        {
2138            return funcall2(requireFunction(first), second, third,
2139                            LispThread.currentThread());
2140        }
2141        public LispObject execute(LispObject[] args) throws ConditionThrowable
2142        {
2143            if (args.length < 1) {
2144                signal(new WrongNumberOfArgumentsException(this));
2145                return NIL;
2146            }
2147            LispObject fun = requireFunction(args[0]);
2148            final int length = args.length - 1; // Number of arguments.
2149
if (length == 3) {
2150                return funcall3(fun, args[1], args[2], args[3],
2151                                LispThread.currentThread());
2152            } else {
2153                LispObject[] funArgs = new LispObject[length];
2154                System.arraycopy(args, 1, funArgs, 0, length);
2155                return funcall(fun, funArgs, LispThread.currentThread());
2156            }
2157        }
2158        private LispObject requireFunction(LispObject arg) throws ConditionThrowable
2159        {
2160            if (arg instanceof Function || arg instanceof GenericFunction)
2161                return arg;
2162            if (arg instanceof Symbol) {
2163                LispObject function = arg.getSymbolFunction();
2164                if (function instanceof Function || function instanceof GenericFunction)
2165                    return function;
2166                return signal(new UndefinedFunction(arg));
2167            }
2168            return signal(new TypeError(arg, list3(Symbol.OR, Symbol.FUNCTION,
2169                                                   Symbol.SYMBOL)));
2170        }
2171    };
2172
2173    // ### apply
2174
public static final Primitive APPLY =
2175        new Primitive("apply", "function &rest args")
2176    {
2177        public LispObject execute(LispObject first, LispObject second)
2178            throws ConditionThrowable
2179        {
2180            LispObject spread = checkList(second);
2181            LispObject fun = first;
2182            if (fun instanceof Symbol)
2183                fun = fun.getSymbolFunction();
2184            if (fun instanceof Function || fun instanceof GenericFunction) {
2185                final int numFunArgs = spread.length();
2186                final LispThread thread = LispThread.currentThread();
2187                switch (numFunArgs) {
2188                    case 1:
2189                        return funcall1(fun, spread.car(), thread);
2190                    case 2:
2191                        return funcall2(fun, spread.car(), spread.cadr(), thread);
2192                    case 3:
2193                        return funcall3(fun, spread.car(), spread.cadr(),
2194                                        spread.cdr().cdr().car(), thread);
2195                    default: {
2196                        final LispObject[] funArgs = new LispObject[numFunArgs];
2197                        int j = 0;
2198                        while (spread != NIL) {
2199                            funArgs[j++] = spread.car();
2200                            spread = spread.cdr();
2201                        }
2202                        return funcall(fun, funArgs, thread);
2203                    }
2204                }
2205            }
2206            signal(new TypeError(fun, "function"));
2207            return NIL;
2208        }
2209        public LispObject execute(final LispObject[] args) throws ConditionThrowable
2210        {
2211            final int numArgs = args.length;
2212            if (numArgs < 2)
2213                signal(new WrongNumberOfArgumentsException(this));
2214            LispObject spread = checkList(args[numArgs - 1]);
2215            LispObject fun = args[0];
2216            if (fun instanceof Symbol)
2217                fun = fun.getSymbolFunction();
2218            if (fun instanceof Function || fun instanceof GenericFunction) {
2219                final int numFunArgs = numArgs - 2 + spread.length();
2220                final LispObject[] funArgs = new LispObject[numFunArgs];
2221                int j = 0;
2222                for (int i = 1; i < numArgs - 1; i++)
2223                    funArgs[j++] = args[i];
2224                while (spread != NIL) {
2225                    funArgs[j++] = spread.car();
2226                    spread = spread.cdr();
2227                }
2228                return funcall(fun, funArgs, LispThread.currentThread());
2229            }
2230            signal(new TypeError(fun, "function"));
2231            return NIL;
2232        }
2233    };
2234
2235    // ### mapcar
2236
private static final Primitive MAPCAR =
2237        new Primitive("mapcar", "function &rest lists")
2238    {
2239        public LispObject execute(LispObject op, LispObject list)
2240            throws ConditionThrowable
2241        {
2242            LispObject fun;
2243            if (op instanceof Symbol)
2244                fun = op.getSymbolFunction();
2245            else
2246                fun = op;
2247            if (fun instanceof Function || fun instanceof GenericFunction) {
2248                final LispThread thread = LispThread.currentThread();
2249                LispObject result = NIL;
2250                LispObject splice = null;
2251                while (list != NIL) {
2252                    LispObject obj = funcall1(fun, list.car(), thread);
2253                    if (splice == null) {
2254                        result = new Cons(obj, result);
2255                        splice = result;
2256                    } else {
2257                        Cons cons = new Cons(obj);
2258                        splice.setCdr(cons);
2259                        splice = cons;
2260                    }
2261                    list = list.cdr();
2262                }
2263                thread.clearValues();
2264                return result;
2265            }
2266            signal(new UndefinedFunction(op));
2267            return NIL;
2268        }
2269
2270        public LispObject execute(LispObject first, LispObject second,
2271                                  LispObject third)
2272            throws ConditionThrowable
2273        {
2274            // First argument must be a function.
2275
LispObject fun = first;
2276            if (fun instanceof Symbol)
2277                fun = fun.getSymbolFunction();
2278            if (!(fun instanceof Function || fun instanceof GenericFunction))
2279                signal(new UndefinedFunction(first));
2280            // Remaining arguments must be lists.
2281
LispObject list1 = checkList(second);
2282            LispObject list2 = checkList(third);
2283            final LispThread thread = LispThread.currentThread();
2284            LispObject result = NIL;
2285            LispObject splice = null;
2286            while (list1 != NIL && list2 != NIL) {
2287                LispObject obj =
2288                    funcall2(fun, list1.car(), list2.car(), thread);
2289                if (splice == null) {
2290                    result = new Cons(obj, result);
2291                    splice = result;
2292                } else {
2293                    Cons cons = new Cons(obj);
2294                    splice.setCdr(cons);
2295                    splice = cons;
2296                }
2297                list1 = list1.cdr();
2298                list2 = list2.cdr();
2299            }
2300            thread.clearValues();
2301            return result;
2302        }
2303
2304        public LispObject execute(final LispObject[] args) throws ConditionThrowable
2305        {
2306            final int numArgs = args.length;
2307            if (numArgs < 2)
2308                signal(new WrongNumberOfArgumentsException(this));
2309            // First argument must be a function.
2310
LispObject fun = args[0];
2311            if (fun instanceof Symbol)
2312                fun = fun.getSymbolFunction();
2313            if (!(fun instanceof Function || fun instanceof GenericFunction))
2314                signal(new UndefinedFunction(args[0]));
2315            // Remaining arguments must be lists.
2316
int commonLength = -1;
2317            for (int i = 1; i < numArgs; i++) {
2318                if (!args[i].listp())
2319                    signal(new TypeError(args[i], "list"));
2320                int len = args[i].length();
2321                if (commonLength < 0)
2322                    commonLength = len;
2323                else if (commonLength > len)
2324                    commonLength = len;
2325            }
2326            final LispThread thread = LispThread.currentThread();
2327            LispObject[] results = new LispObject[commonLength];
2328            final int numFunArgs = numArgs - 1;
2329            final LispObject[] funArgs = new LispObject[numFunArgs];
2330            for (int i = 0; i < commonLength; i++) {
2331                for (int j = 0; j < numFunArgs; j++)
2332                    funArgs[j] = args[j+1].car();
2333                results[i] = funcall(fun, funArgs, thread);
2334                for (int j = 1; j < numArgs; j++)
2335                    args[j] = args[j].cdr();
2336            }
2337            thread.clearValues();
2338            LispObject result = NIL;
2339            for (int i = commonLength; i-- > 0;)
2340                result = new Cons(results[i], result);
2341            return result;
2342        }
2343    };
2344
2345    // ### macroexpand
2346
private static final Primitive MACROEXPAND =
2347        new Primitive("macroexpand", "form &optional env")
2348    {
2349        public LispObject execute(LispObject[] args) throws ConditionThrowable
2350        {
2351            final int length = args.length;
2352            if (length < 1 || length > 2)
2353                signal(new WrongNumberOfArgumentsException(this));
2354            LispObject form = args[0];
2355            final Environment env;
2356            if (length == 2 && args[1] != NIL)
2357                env = checkEnvironment(args[1]);
2358            else
2359                env = new Environment();
2360            return macroexpand(form, env, LispThread.currentThread());
2361        }
2362    };
2363
2364    // ### macroexpand-1
2365
private static final Primitive MACROEXPAND_1 =
2366        new Primitive("macroexpand-1", "form &optional env")
2367    {
2368        public LispObject execute(LispObject form) throws ConditionThrowable
2369        {
2370            return macroexpand_1(form,
2371                                 new Environment(),
2372                                 LispThread.currentThread());
2373        }
2374        public LispObject execute(LispObject form, LispObject env)
2375            throws ConditionThrowable
2376        {
2377            return macroexpand_1(form,
2378                                 env != NIL ? checkEnvironment(env) : new Environment(),
2379                                 LispThread.currentThread());
2380        }
2381    };
2382
2383    // ### *gensym-counter*
2384
private static final Symbol _GENSYM_COUNTER_ =
2385        PACKAGE_CL.addExternalSymbol("*GENSYM-COUNTER*");
2386    static {
2387        _GENSYM_COUNTER_.setSymbolValue(Fixnum.ZERO);
2388        _GENSYM_COUNTER_.setSpecial(true);
2389    }
2390
2391    // ### gensym
2392
private static final Primitive GENSYM = new Primitive("gensym", "&optional x")
2393    {
2394        public LispObject execute() throws ConditionThrowable
2395        {
2396            return gensym("G");
2397        }
2398        public LispObject execute(LispObject arg) throws ConditionThrowable
2399        {
2400            String JavaDoc prefix = "G";
2401            if (arg instanceof Fixnum) {
2402                int n = ((Fixnum)arg).getValue();
2403                if (n < 0)
2404                    signal(new TypeError(arg, "non-negative integer"));
2405                StringBuffer JavaDoc sb = new StringBuffer JavaDoc(prefix);
2406                sb.append(n);
2407                return new Symbol(sb.toString());
2408            }
2409            if (arg instanceof Bignum) {
2410                BigInteger JavaDoc n = ((Bignum)arg).getValue();
2411                if (n.signum() < 0)
2412                    signal(new TypeError(arg, "non-negative integer"));
2413                StringBuffer JavaDoc sb = new StringBuffer JavaDoc(prefix);
2414                sb.append(n.toString());
2415                return new Symbol(sb.toString());
2416            }
2417            if (arg instanceof AbstractString)
2418                prefix = arg.getStringValue();
2419            else
2420                signal(new TypeError(arg, "string or non-negative integer"));
2421            return gensym(prefix);
2422        }
2423    };
2424
2425    private static final Symbol gensym(String JavaDoc prefix) throws ConditionThrowable
2426    {
2427        LispThread thread = LispThread.currentThread();
2428        Environment dynEnv = thread.getDynamicEnvironment();
2429        Binding binding =
2430            (dynEnv == null) ? null : dynEnv.getBinding(_GENSYM_COUNTER_);
2431        LispObject oldValue;
2432        if (binding != null) {
2433            oldValue = binding.value;
2434            binding.value = oldValue.incr();
2435        } else {
2436            oldValue = _GENSYM_COUNTER_.getSymbolValue();
2437            _GENSYM_COUNTER_.setSymbolValue(oldValue.incr());
2438        }
2439        StringBuffer JavaDoc sb = new StringBuffer JavaDoc(prefix);
2440        sb.append(oldValue.writeToString());
2441        return new Symbol(sb.toString());
2442    }
2443
2444    // ### string
2445
private static final Primitive1 STRING = new Primitive1("string", "x")
2446    {
2447        public LispObject execute(LispObject arg) throws ConditionThrowable
2448        {
2449            return arg.STRING();
2450        }
2451    };
2452
2453    // ### intern
2454
// intern string &optional package => symbol, status
2455
// status is one of :INHERITED, :EXTERNAL, :INTERNAL or NIL.
2456
private static final Primitive INTERN =
2457        new Primitive("intern", "string &optional package")
2458    {
2459        public LispObject execute(LispObject arg) throws ConditionThrowable
2460        {
2461            String JavaDoc s = arg.getStringValue();
2462            final LispThread thread = LispThread.currentThread();
2463            Package JavaDoc pkg = (Package JavaDoc) _PACKAGE_.symbolValueNoThrow(thread);
2464            return pkg.intern(s, thread);
2465        }
2466
2467        public LispObject execute(LispObject first, LispObject second)
2468            throws ConditionThrowable
2469        {
2470            String JavaDoc s = first.getStringValue();
2471            Package JavaDoc pkg = coerceToPackage(second);
2472            return pkg.intern(s, LispThread.currentThread());
2473        }
2474    };
2475
2476    // ### unintern
2477
// unintern symbol &optional package => generalized-boolean
2478
private static final Primitive UNINTERN =
2479        new Primitive("unintern", "symbol &optional package")
2480    {
2481        public LispObject execute(LispObject[] args) throws ConditionThrowable
2482        {
2483            if (args.length == 0 || args.length > 2)
2484                signal(new WrongNumberOfArgumentsException(this));
2485            Symbol symbol = checkSymbol(args[0]);
2486            Package JavaDoc pkg;
2487            if (args.length == 2)
2488                pkg = coerceToPackage(args[1]);
2489            else
2490                pkg = getCurrentPackage();
2491            return pkg.unintern(symbol);
2492        }
2493    };
2494
2495    // ### find-package
2496
private static final Primitive1 FIND_PACKAGE =
2497        new Primitive1("find-package", "name") {
2498        public LispObject execute(LispObject arg) throws ConditionThrowable
2499        {
2500            if (arg instanceof Package JavaDoc)
2501                return arg;
2502            if (arg instanceof AbstractString) {
2503                Package JavaDoc pkg =
2504                    Packages.findPackage(arg.getStringValue());
2505                return pkg != null ? pkg : NIL;
2506            }
2507            if (arg instanceof Symbol) {
2508                Package JavaDoc pkg = Packages.findPackage(arg.getName());
2509                return pkg != null ? pkg : NIL;
2510            }
2511            if (arg instanceof LispCharacter) {
2512                String JavaDoc packageName =
2513                    String.valueOf(new char[] {((LispCharacter)arg).getValue()});
2514                Package JavaDoc pkg = Packages.findPackage(packageName);
2515                return pkg != null ? pkg : NIL;
2516            }
2517            return NIL;
2518        }
2519    };
2520
2521    // ### %make-package
2522
// %make-package package-name nicknames use => package
2523
private static final Primitive3 _MAKE_PACKAGE =
2524        new Primitive3("%make-package", PACKAGE_SYS, false) {
2525        public LispObject execute(LispObject first, LispObject second,
2526                                  LispObject third)
2527            throws ConditionThrowable
2528        {
2529            String JavaDoc packageName = javaString(first);
2530            Package JavaDoc pkg =
2531                Packages.findPackage(packageName);
2532            if (pkg != null)
2533                signal(new LispError("Package " + packageName +
2534                                     " already exists."));
2535            LispObject nicknames = checkList(second);
2536            if (nicknames != NIL) {
2537                LispObject list = nicknames;
2538                while (list != NIL) {
2539                    String JavaDoc nick = javaString(list.car());
2540                    if (Packages.findPackage(nick) != null) {
2541                        signal(new PackageError("A package named " + nick +
2542                                                " already exists."));
2543                    }
2544                    list = list.cdr();
2545                }
2546            }
2547            LispObject use = checkList(third);
2548            if (use != NIL) {
2549                LispObject list = use;
2550                while (list != NIL) {
2551                    LispObject obj = list.car();
2552                    if (obj instanceof Package JavaDoc)
2553                        ; // OK.
2554
else {
2555                        String JavaDoc s = javaString(obj);
2556                        Package JavaDoc p = Packages.findPackage(s);
2557                        if (p == null) {
2558                            signal(new LispError(obj.writeToString() +
2559                                                 " is not the name of a package."));
2560                            return NIL;
2561                        }
2562                    }
2563                    list = list.cdr();
2564                }
2565            }
2566            // Now create the package.
2567
pkg = Packages.createPackage(packageName);
2568            // Add the nicknames.
2569
while (nicknames != NIL) {
2570                String JavaDoc nick = javaString(nicknames.car());
2571                pkg.addNickname(nick);
2572                nicknames = nicknames.cdr();
2573            }
2574            // Create the use list.
2575
while (use != NIL) {
2576                LispObject obj = use.car();
2577                if (obj instanceof Package JavaDoc)
2578                    pkg.usePackage((Package JavaDoc)obj);
2579                else {
2580                    String JavaDoc s = javaString(obj);
2581                    Package JavaDoc p = Packages.findPackage(s);
2582                    if (p == null) {
2583                        signal(new LispError(obj.writeToString() +
2584                                             " is not the name of a package."));
2585                        return NIL;
2586                    }
2587                    pkg.usePackage(p);
2588                }
2589                use = use.cdr();
2590            }
2591            return pkg;
2592        }
2593    };
2594
2595    // ### %in-package
2596
private static final Primitive1 _IN_PACKAGE =
2597        new Primitive1("%in-package", PACKAGE_SYS, false)
2598    {
2599        public LispObject execute(LispObject arg) throws ConditionThrowable
2600        {
2601            String JavaDoc packageName = javaString(arg);
2602            Package JavaDoc pkg = Packages.findPackage(packageName);
2603            if (pkg == null)
2604                signal(new PackageError("The name " + packageName +
2605                                        " does not designate any package."));
2606            LispThread thread = LispThread.currentThread();
2607            Environment dynEnv = thread.getDynamicEnvironment();
2608            if (dynEnv != null) {
2609                Binding binding = dynEnv.getBinding(_PACKAGE_);
2610                if (binding != null) {
2611                    binding.value = pkg;
2612                    return pkg;
2613                }
2614            }
2615            // No dynamic binding.
2616
_PACKAGE_.setSymbolValue(pkg);
2617            return pkg;
2618        }
2619    };
2620
2621    // ### use-package
2622
// use-package packages-to-use &optional package => t
2623
private static final Primitive USE_PACKAGE =
2624        new Primitive("use-package","packages-to-use &optional package")
2625    {
2626        public LispObject execute(LispObject[] args) throws ConditionThrowable
2627        {
2628            if (args.length < 1 || args.length > 2)
2629                signal(new WrongNumberOfArgumentsException(this));
2630            Package JavaDoc pkg;
2631            if (args.length == 2)
2632                pkg = coerceToPackage(args[1]);
2633            else
2634                pkg = getCurrentPackage();
2635            if (args[0] instanceof Cons) {
2636                LispObject list = args[0];
2637                while (list != NIL) {
2638                    pkg.usePackage(coerceToPackage(list.car()));
2639                    list = list.cdr();
2640                }
2641            } else
2642                pkg.usePackage(coerceToPackage(args[0]));
2643            return T;
2644        }
2645    };
2646
2647    // ### package-symbols
2648
private static final Primitive1 PACKAGE_SYMBOLS =
2649        new Primitive1("package-symbols", PACKAGE_SYS, false)
2650    {
2651        public LispObject execute(LispObject arg) throws ConditionThrowable
2652        {
2653            return coerceToPackage(arg).getSymbols();
2654        }
2655    };
2656
2657    // ### package-internal-symbols
2658
private static final Primitive1 PACKAGE_INTERNAL_SYMBOLS =
2659        new Primitive1("package-internal-symbols", PACKAGE_SYS, false)
2660    {
2661        public LispObject execute(LispObject arg) throws ConditionThrowable
2662        {
2663            return coerceToPackage(arg).PACKAGE_INTERNAL_SYMBOLS();
2664        }
2665    };
2666
2667    // ### package-external-symbols
2668
private static final Primitive1 PACKAGE_EXTERNAL_SYMBOLS =
2669        new Primitive1("package-external-symbols", PACKAGE_SYS, false)
2670    {
2671        public LispObject execute(LispObject arg) throws ConditionThrowable
2672        {
2673            return coerceToPackage(arg).PACKAGE_EXTERNAL_SYMBOLS();
2674        }
2675    };
2676
2677    // ### package-inherited-symbols
2678
private static final Primitive1 PACKAGE_INHERITED_SYMBOLS =
2679        new Primitive1("package-inherited-symbols", PACKAGE_SYS, false)
2680    {
2681        public LispObject execute(LispObject arg) throws ConditionThrowable
2682        {
2683            return coerceToPackage(arg).PACKAGE_INHERITED_SYMBOLS();
2684        }
2685    };
2686
2687    // ### export symbols &optional package
2688
private static final Primitive EXPORT =
2689        new Primitive("export", "symbols &optional package")
2690    {
2691        public LispObject execute(LispObject arg) throws ConditionThrowable
2692        {
2693            if (arg instanceof Cons) {
2694                Package JavaDoc pkg = getCurrentPackage();
2695                for (LispObject list = arg; list != NIL; list = list.cdr())
2696                    pkg.export(checkSymbol(list.car()));
2697            } else
2698                getCurrentPackage().export(checkSymbol(arg));
2699            return T;
2700        }
2701
2702        public LispObject execute(LispObject first, LispObject second)
2703            throws ConditionThrowable
2704        {
2705            if (first instanceof Cons) {
2706                Package JavaDoc pkg = coerceToPackage(second);
2707                for (LispObject list = first; list != NIL; list = list.cdr())
2708                    pkg.export(checkSymbol(list.car()));
2709            } else
2710                coerceToPackage(second).export(checkSymbol(first));
2711            return T;
2712        }
2713    };
2714
2715    // ### find-symbol string &optional package => symbol, status
2716
private static final Primitive FIND_SYMBOL =
2717        new Primitive("find-symbol", "string &optional package")
2718    {
2719        public LispObject execute(LispObject arg) throws ConditionThrowable
2720        {
2721            return getCurrentPackage().findSymbol(arg.getStringValue());
2722        }
2723
2724        public LispObject execute(LispObject first, LispObject second)
2725            throws ConditionThrowable
2726        {
2727            return coerceToPackage(second).findSymbol(first.getStringValue());
2728        }
2729    };
2730
2731    // ### fset name function &optional source-position arglist => function
2732
private static final Primitive FSET =
2733        new Primitive("fset", PACKAGE_SYS, false)
2734    {
2735        public LispObject execute(LispObject first, LispObject second)
2736            throws ConditionThrowable
2737        {
2738            return execute(first, second, NIL, NIL);
2739        }
2740
2741        public LispObject execute(LispObject first, LispObject second,
2742                                  LispObject third)
2743            throws ConditionThrowable
2744        {
2745            return execute(first, second, third, NIL);
2746        }
2747
2748        public LispObject execute(LispObject first, LispObject second,
2749                                  LispObject third, LispObject fourth)
2750            throws ConditionThrowable
2751        {
2752            if (first instanceof Symbol) {
2753                Symbol symbol = (Symbol) first;
2754                symbol.setSymbolFunction(second);
2755                LispObject source = Load._FASL_SOURCE_.symbolValue();
2756                if (source != NIL) {
2757                    if (third != NIL)
2758                        put(symbol, Symbol._SOURCE, new Cons(source, third));
2759                    else
2760                        put(symbol, Symbol._SOURCE, source);
2761                }
2762            } else if (first instanceof Cons && first.car() == Symbol.SETF) {
2763                // SETF function
2764
Symbol symbol = checkSymbol(first.cadr());
2765                put(symbol, Symbol._SETF_FUNCTION, second);
2766            } else
2767                return signal(new TypeError(first.writeToString() +
2768                                            " is not a valid function name."));
2769            if (second instanceof Functional) {
2770                ((Functional)second).setLambdaName(first);
2771                if (fourth != NIL)
2772                    ((Functional)second).setArglist(fourth);
2773            }
2774            return second;
2775        }
2776    };
2777
2778    // ### %set-symbol-plist
2779
private static final Primitive2 _SET_SYMBOL_PLIST =
2780        new Primitive2("%set-symbol-plist", PACKAGE_SYS, false)
2781    {
2782        public LispObject execute(LispObject first, LispObject second)
2783            throws ConditionThrowable
2784        {
2785            checkSymbol(first).setPropertyList(checkList(second));
2786            return second;
2787        }
2788    };
2789
2790    // ### getf
2791
// getf plist indicator &optional default => value
2792
private static final Primitive GETF =
2793        new Primitive("getf", "plist indicator &optional default")
2794    {
2795        public LispObject execute(LispObject plist, LispObject indicator)
2796            throws ConditionThrowable
2797        {
2798            return getf(plist, indicator, NIL);
2799        }
2800
2801        public LispObject execute(LispObject plist, LispObject indicator,
2802                                  LispObject defaultValue)
2803            throws ConditionThrowable
2804        {
2805            return getf(plist, indicator, defaultValue);
2806        }
2807    };
2808
2809    // ### get
2810
// get symbol indicator &optional default => value
2811
private static final Primitive GET =
2812        new Primitive("get", "symbol indicator &optional default")
2813    {
2814        public LispObject execute(LispObject symbol, LispObject indicator)
2815            throws ConditionThrowable
2816        {
2817            try {
2818                return get((Symbol)symbol, indicator, NIL);
2819            }
2820            catch (ClassCastException JavaDoc e) {
2821                return signal(new TypeError(symbol, Symbol.SYMBOL));
2822            }
2823        }
2824
2825        public LispObject execute(LispObject symbol, LispObject indicator,
2826                                  LispObject defaultValue)
2827            throws ConditionThrowable
2828        {
2829            try {
2830                return get((Symbol)symbol, indicator, defaultValue);
2831            }
2832            catch (ClassCastException JavaDoc e) {
2833                return signal(new TypeError(symbol, Symbol.SYMBOL));
2834            }
2835        }
2836    };
2837
2838    // ### %put
2839
// %put symbol indicator value => value
2840
private static final Primitive _PUT =
2841        new Primitive("%put", PACKAGE_SYS, false)
2842    {
2843        public LispObject execute(LispObject symbol, LispObject indicator,
2844                                  LispObject value)
2845            throws ConditionThrowable
2846        {
2847            return put(checkSymbol(symbol), indicator, value);
2848        }
2849        public LispObject execute(LispObject symbol, LispObject indicator,
2850                                  LispObject defaultValue, LispObject value)
2851            throws ConditionThrowable
2852        {
2853            return put(checkSymbol(symbol), indicator, value);
2854        }
2855    };
2856
2857    // ### macrolet
2858
private static final SpecialOperator MACROLET = new SpecialOperator("macrolet", "definitions &rest body")
2859    {
2860        public LispObject execute(LispObject args, Environment env)
2861            throws ConditionThrowable
2862        {
2863            LispObject defs = checkList(args.car());
2864            final LispThread thread = LispThread.currentThread();
2865            LispObject result;
2866            if (defs != NIL) {
2867                Environment ext = new Environment(env);
2868                while (defs != NIL) {
2869                    LispObject def = checkList(defs.car());
2870                    Symbol symbol = checkSymbol(def.car());
2871                    LispObject lambdaList = def.cadr();
2872                    LispObject body = def.cddr();
2873                    LispObject block =
2874                        new Cons(Symbol.BLOCK, new Cons(symbol, body));
2875                    LispObject toBeApplied =
2876                        list3(Symbol.LAMBDA, lambdaList, block);
2877                    LispObject formArg = gensym("FORM-");
2878                    LispObject envArg = gensym("ENV-"); // Ignored.
2879
LispObject expander =
2880                        list3(Symbol.LAMBDA, list2(formArg, envArg),
2881                              list3(Symbol.APPLY, toBeApplied,
2882                                    list2(Symbol.CDR, formArg)));
2883                    Closure expansionFunction =
2884                        new Closure(expander.cadr(), expander.cddr(), env);
2885                    MacroObject macroObject =
2886                        new MacroObject(expansionFunction);
2887                    ext.bindFunctional(symbol, macroObject);
2888                    defs = defs.cdr();
2889                }
2890                result = progn(args.cdr(), ext, thread);
2891            } else
2892                result = progn(args.cdr(), env, thread);
2893            return result;
2894        }
2895    };
2896
2897    // ### tagbody
2898
private static final SpecialOperator TAGBODY = new SpecialOperator("tagbody", "&rest statements")
2899    {
2900        public LispObject execute(LispObject args, Environment env)
2901            throws ConditionThrowable
2902        {
2903            Environment ext = new Environment(env);
2904            LispObject localTags = NIL; // Tags that are local to this TAGBODY.
2905
LispObject body = args;
2906            while (body != NIL) {
2907                LispObject current = body.car();
2908                body = body.cdr();
2909                if (current instanceof Cons)
2910                    continue;
2911                // It's a tag.
2912
ext.addTagBinding(current, body);
2913                localTags = new Cons(current, localTags);
2914            }
2915            final LispThread thread = LispThread.currentThread();
2916            final LispObject stack = thread.getStack();
2917            LispObject remaining = args;
2918            while (remaining != NIL) {
2919                LispObject current = remaining.car();
2920                if (current instanceof Cons) {
2921                    try {
2922                        // Handle GO inline if possible.
2923
if (current.car() == Symbol.GO) {
2924                            if (interrupted)
2925                                handleInterrupt();
2926                            LispObject tag = current.cadr();
2927                            if (memql(tag, localTags)) {
2928                                Binding binding = ext.getTagBinding(tag);
2929                                if (binding != null && binding.value != null) {
2930                                    remaining = binding.value;
2931                                    continue;
2932                                }
2933                            }
2934                            throw new Go(tag);
2935                        }
2936                        eval(current, ext, thread);
2937                    }
2938                    catch (Go go) {
2939                        LispObject tag = go.getTag();
2940                        if (memql(tag, localTags)) {
2941                            Binding binding = ext.getTagBinding(tag);
2942                            if (binding != null && binding.value != null) {
2943                                remaining = binding.value;
2944                                thread.setStack(stack);
2945                                continue;
2946                            }
2947                        }
2948                        throw go;
2949                    }
2950                }
2951                remaining = remaining.cdr();
2952            }
2953            thread.clearValues();
2954            return NIL;
2955        }
2956    };
2957
2958    // ### go
2959
private static final SpecialOperator GO = new SpecialOperator("go", "tag")
2960    {
2961        public LispObject execute(LispObject args, Environment env)
2962            throws ConditionThrowable
2963        {
2964            if (args.length() != 1)
2965                signal(new WrongNumberOfArgumentsException(this));
2966            Binding binding = env.getTagBinding(args.car());
2967            if (binding == null)
2968                return signal(new ControlError("No tag named " +
2969                                               args.car().writeToString() +
2970                                               " is currently visible."));
2971            throw new Go(args.car());
2972        }
2973    };
2974
2975    // ### block
2976
private static final SpecialOperator BLOCK = new SpecialOperator("block", "name &rest forms")
2977    {
2978        public LispObject execute(LispObject args, Environment env)
2979            throws ConditionThrowable
2980        {
2981            if (args == NIL)
2982                signal(new WrongNumberOfArgumentsException(this));
2983            LispObject tag;
2984            try {
2985                tag = (Symbol) args.car();
2986            }
2987            catch (ClassCastException JavaDoc e) {
2988                return signal(new TypeError(args.car(), Symbol.SYMBOL));
2989            }
2990            LispObject body = args.cdr();
2991            Environment ext = new Environment(env);
2992            final LispObject block = new LispObject();
2993            ext.addBlock(tag, block);
2994            LispObject result = NIL;
2995            final LispThread thread = LispThread.currentThread();
2996            final LispObject stack = thread.getStack();
2997            try {
2998                while (body != NIL) {
2999                    result = eval(body.car(), ext, thread);
3000                    body = body.cdr();
3001                }
3002                return result;
3003            }
3004            catch (Return ret) {
3005                if (ret.getBlock() == block) {
3006                    thread.setStack(stack);
3007                    return ret.getResult();
3008                }
3009                throw ret;
3010            }
3011        }
3012    };
3013
3014    // ### return-from
3015
private static final SpecialOperator RETURN_FROM =
3016        new SpecialOperator("return-from", "name &optional value")
3017    {
3018        public LispObject execute(LispObject args, Environment env)
3019            throws ConditionThrowable
3020        {
3021            final int length = args.length();
3022            if (length < 1 || length > 2)
3023                signal(new WrongNumberOfArgumentsException(this));
3024            LispObject symbol;
3025            try {
3026                symbol = (Symbol) args.car();
3027            }
3028            catch (ClassCastException JavaDoc e) {
3029                return signal(new TypeError(args.car(), Symbol.SYMBOL));
3030            }
3031            LispObject block = env.lookupBlock(symbol);
3032            if (block == null) {
3033                StringBuffer JavaDoc sb = new StringBuffer JavaDoc("No block named ");
3034                sb.append(symbol.getName());
3035                sb.append(" is currently visible.");
3036                signal(new LispError(sb.toString()));
3037            }
3038            LispObject result;
3039            if (length == 2)
3040                result = eval(args.cadr(), env, LispThread.currentThread());
3041            else
3042                result = NIL;
3043            throw new Return(symbol, block, result);
3044        }
3045    };
3046
3047    // ### catch
3048
private static final SpecialOperator CATCH = new SpecialOperator("catch", "tag &body body")
3049    {
3050        public LispObject execute(LispObject args, Environment env)
3051            throws ConditionThrowable
3052        {
3053            if (args.length() < 1)
3054                signal(new WrongNumberOfArgumentsException(this));
3055            final LispThread thread = LispThread.currentThread();
3056            LispObject tag = eval(args.car(), env, thread);
3057            thread.pushCatchTag(tag);
3058            LispObject body = args.cdr();
3059            LispObject result = NIL;
3060            final LispObject stack = thread.getStack();
3061            try {
3062                while (body != NIL) {
3063                    result = eval(body.car(), env, thread);
3064                    body = body.cdr();
3065                }
3066                return result;
3067            }
3068            catch (Throw t) {
3069                if (t.tag == tag) {
3070                    thread.setStack(stack);
3071                    return t.getResult(thread);
3072                }
3073                throw t;
3074            }
3075            catch (Return ret) {
3076                throw ret;
3077            }
3078            finally {
3079                thread.popCatchTag();
3080            }
3081        }
3082    };
3083
3084    // ### throw
3085
private static final SpecialOperator THROW = new SpecialOperator("throw", "tag result")
3086    {
3087        public LispObject execute(LispObject args, Environment env)
3088            throws ConditionThrowable
3089        {
3090            if (args.length() != 2)
3091                signal(new WrongNumberOfArgumentsException(this));
3092            final LispThread thread = LispThread.currentThread();
3093            thread.throwToTag(eval(args.car(), env, thread),
3094                              eval(args.cadr(), env, thread));
3095            // Not reached.
3096
return NIL;
3097        }
3098    };
3099
3100    // ### unwind-protect
3101
private static final SpecialOperator UNWIND_PROTECT =
3102        new SpecialOperator("unwind-protect", "protected &body cleanup")
3103    {
3104        public LispObject execute(LispObject args, Environment env)
3105            throws ConditionThrowable
3106        {
3107            final LispThread thread = LispThread.currentThread();
3108            LispObject result;
3109            LispObject[] values;
3110            try {
3111                result = eval(args.car(), env, thread);
3112                values = thread.getValues();
3113            }
3114            finally {
3115                LispObject body = args.cdr();
3116                while (body != NIL) {
3117                    eval(body.car(), env, thread);
3118                    body = body.cdr();
3119                }
3120            }
3121            if (values != null)
3122                thread.setValues(values);
3123            else
3124                thread.clearValues();
3125            return result;
3126        }
3127    };
3128
3129    // ### eval-when
3130
private static final SpecialOperator EVAL_WHEN =
3131        new SpecialOperator("eval-when", "situations &rest forms")
3132    {
3133        public LispObject execute(LispObject args, Environment env)
3134            throws ConditionThrowable
3135        {
3136            LispObject situations = args.car();
3137            if (situations != NIL) {
3138                final LispThread thread = LispThread.currentThread();
3139                if (memq(Keyword.EXECUTE, situations) ||
3140                    memq(Symbol.EVAL, situations))
3141                {
3142                    return progn(args.cdr(), env, thread);
3143                }
3144            }
3145            return NIL;
3146        }
3147    };
3148
3149    // ### multiple-value-bind
3150
// multiple-value-bind (var*) values-form declaration* form*
3151
// Should be a macro.
3152
private static final SpecialOperator MULTIPLE_VALUE_BIND =
3153        new SpecialOperator("multiple-value-bind", "vars value-form &body body") {
3154        public LispObject execute(LispObject args, Environment env)
3155            throws ConditionThrowable
3156        {
3157            LispObject vars = args.car();
3158            args = args.cdr();
3159            LispObject valuesForm = args.car();
3160            LispObject body = args.cdr();
3161            final LispThread thread = LispThread.currentThread();
3162            LispObject value = eval(valuesForm, env, thread);
3163            LispObject[] values = thread.getValues();
3164            if (values == null) {
3165                // eval() did not return multiple values.
3166
values = new LispObject[1];
3167                values[0] = value;
3168            }
3169            // Process declarations.
3170
LispObject specials = NIL;
3171            while (body != NIL) {
3172                LispObject obj = body.car();
3173                if (obj instanceof Cons && obj.car() == Symbol.DECLARE) {
3174                    LispObject decls = obj.cdr();
3175                    while (decls != NIL) {
3176                        LispObject decl = decls.car();
3177                        if (decl instanceof Cons && decl.car() == Symbol.SPECIAL) {
3178                            LispObject declvars = decl.cdr();
3179                            while (declvars != NIL) {
3180                                specials = new Cons(declvars.car(), specials);
3181                                declvars = declvars.cdr();
3182                            }
3183                        }
3184                        decls = decls.cdr();
3185                    }
3186                    body = body.cdr();
3187                } else
3188                    break;
3189            }
3190            final Environment oldDynEnv = thread.getDynamicEnvironment();
3191            final Environment ext = new Environment(env);
3192            int i = 0;
3193            LispObject var = vars.car();
3194            while (var != NIL) {
3195                Symbol sym = checkSymbol(var);
3196                LispObject val = i < values.length ? values[i] : NIL;
3197                if (specials != NIL && memq(sym, specials)) {
3198                    thread.bindSpecial(sym, val);
3199                    ext.declareSpecial(sym);
3200                } else if (sym.isSpecialVariable()) {
3201                    thread.bindSpecial(sym, val);
3202                } else
3203                    ext.bind(sym, val);
3204                vars = vars.cdr();
3205                var = vars.car();
3206                ++i;
3207            }
3208            thread._values = null;
3209            LispObject result = NIL;
3210            try {
3211                while (body != NIL) {
3212                    result = eval(body.car(), ext, thread);
3213                    body = body.cdr();
3214                }
3215            }
3216            finally {
3217                thread.setDynamicEnvironment(oldDynEnv);
3218            }
3219            return result;
3220        }
3221    };
3222
3223    // ### multiple-value-prog1
3224
private static final SpecialOperator MULTIPLE_VALUE_PROG1 =
3225        new SpecialOperator("multiple-value-prog1", "values-form &rest forms")
3226    {
3227        public LispObject execute(LispObject args, Environment env)
3228            throws ConditionThrowable
3229        {
3230            if (args.length() == 0)
3231                signal(new WrongNumberOfArgumentsException(this));
3232            final LispThread thread = LispThread.currentThread();
3233            LispObject result = eval(args.car(), env, thread);
3234            LispObject[] values = thread.getValues();
3235            while ((args = args.cdr()) != NIL)
3236                eval(args.car(), env, thread);
3237            if (values != null)
3238                thread.setValues(values);
3239            else
3240                thread.clearValues();
3241            return result;
3242        }
3243    };
3244
3245    // ### multiple-value-call
3246
private static final SpecialOperator MULTIPLE_VALUE_CALL =
3247        new SpecialOperator("multiple-value-call", "fun &rest args")
3248    {
3249        public LispObject execute(LispObject args, Environment env)
3250            throws ConditionThrowable
3251        {
3252            if (args.length() == 0)
3253                signal(new WrongNumberOfArgumentsException(this));
3254            final LispThread thread = LispThread.currentThread();
3255            LispObject function;
3256            LispObject obj = eval(args.car(), env, thread);
3257            args = args.cdr();
3258            if (obj instanceof Symbol) {
3259                function = obj.getSymbolFunction();
3260                if (function == null)
3261                    signal(new UndefinedFunction(obj));
3262            } else if (obj instanceof Function) {
3263                function = obj;
3264            } else {
3265                signal(new LispError(obj.writeToString() +
3266                                     " is not a function name."));
3267                return NIL;
3268            }
3269            ArrayList JavaDoc arrayList = new ArrayList JavaDoc();
3270            while (args != NIL) {
3271                LispObject form = args.car();
3272                LispObject result = eval(form, env, thread);
3273                LispObject[] values = thread.getValues();
3274                if (values != null) {
3275                    for (int i = 0; i < values.length; i++)
3276                        arrayList.add(values[i]);
3277                } else
3278                    arrayList.add(result);
3279                args = args.cdr();
3280            }
3281            LispObject[] argv = new LispObject[arrayList.size()];
3282            arrayList.toArray(argv);
3283            return funcall(function, argv, thread);
3284        }
3285    };
3286
3287    // ### and
3288
// Should be a macro.
3289
private static final SpecialOperator AND = new SpecialOperator("and", "&rest forms") {
3290        public LispObject execute(LispObject args, Environment env)
3291            throws ConditionThrowable
3292        {
3293            final LispThread thread = LispThread.currentThread();
3294            LispObject result = T;
3295            while (args != NIL) {
3296                result = eval(args.car(), env, thread);
3297                if (result == NIL) {
3298                    if (args.cdr() != NIL) {
3299                        // Not the last form.
3300
thread.clearValues();
3301                    }
3302                    break;
3303                }
3304                args = args.cdr();
3305            }
3306            return result;
3307        }
3308    };
3309
3310    // ### or
3311
// Should be a macro.
3312
private static final SpecialOperator OR = new SpecialOperator("or", "&rest forms") {
3313        public LispObject execute(LispObject args, Environment env)
3314            throws ConditionThrowable
3315        {
3316            final LispThread thread = LispThread.currentThread();
3317            LispObject result = NIL;
3318            while (args != NIL) {
3319                result = eval(args.car(), env, thread);
3320                if (result != NIL) {
3321                    if (args.cdr() != NIL) {
3322                        // Not the last form.
3323
thread.clearValues();
3324                    }
3325                    break;
3326                }
3327                args = args.cdr();
3328            }
3329            return result;
3330        }
3331    };
3332
3333    // ### %write-char
3334
// %write-char character output-stream => character
3335
private static final Primitive2 _WRITE_CHAR =
3336        new Primitive2("%write-char", PACKAGE_SYS, false,
3337                       "character output-stream")
3338    {
3339        public LispObject execute(LispObject first, LispObject second)
3340            throws ConditionThrowable
3341        {
3342            outSynonymOf(second)._writeChar(LispCharacter.getValue(first));
3343            return first;
3344        }
3345    };
3346
3347    // ### %write-string
3348
// write-string string output-stream start end => string
3349
private static final Primitive4 _WRITE_STRING =
3350        new Primitive4("%write-string", PACKAGE_SYS, false,
3351                       "string output-stream start end")
3352    {
3353        public LispObject execute(LispObject first, LispObject second,
3354                                  LispObject third, LispObject fourth)
3355            throws ConditionThrowable
3356        {
3357            AbstractString s;
3358            try {
3359                s = (AbstractString) first;
3360            }
3361            catch (ClassCastException JavaDoc e) {
3362                return signal(new TypeError(first, Symbol.STRING));
3363            }
3364            char[] chars = s.chars();
3365            Stream out = outSynonymOf(second);
3366            int start = Fixnum.getValue(third);
3367            int end;
3368            if (fourth == NIL)
3369                end = chars.length;
3370            else
3371                end = Fixnum.getValue(fourth);
3372            checkBounds(start, end, chars.length);
3373            out._writeChars(chars, start, end);
3374            return first;
3375        }
3376    };
3377
3378    // ### %finish-output output-stream => nil
3379
private static final Primitive1 _FINISH_OUTPUT =
3380        new Primitive1("%finish-output", PACKAGE_SYS, false, "output-stream")
3381    {
3382        public LispObject execute(LispObject arg) throws ConditionThrowable
3383        {
3384            return finishOutput(arg);
3385        }
3386    };
3387
3388    // ### %force-output output-stream => nil
3389
private static final Primitive1 _FORCE_OUTPUT =
3390        new Primitive1("%force-output", PACKAGE_SYS, false, "output-stream")
3391    {
3392        public LispObject execute(LispObject arg) throws ConditionThrowable
3393        {
3394            return finishOutput(arg);
3395        }
3396    };
3397
3398    private static final LispObject finishOutput(LispObject arg)
3399        throws ConditionThrowable
3400    {
3401        Stream out = null;
3402        if (arg == T)
3403            out = checkCharacterOutputStream(_TERMINAL_IO_.symbolValue());
3404        else if (arg == NIL)
3405            out = checkCharacterOutputStream(_STANDARD_OUTPUT_.symbolValue());
3406        else if (arg instanceof Stream) {
3407            Stream stream = (Stream) arg;
3408            if (stream instanceof TwoWayStream)
3409                out = ((TwoWayStream)arg).getOutputStream();
3410            else if (stream.isOutputStream())
3411                out = stream;
3412        }
3413        if (out == null)
3414            signal(new TypeError(arg, "output stream"));
3415        return out.finishOutput();
3416    }
3417
3418    // ### clear-input
3419
// clear-input &optional input-stream => nil
3420
private static final Primitive CLEAR_INPUT =
3421        new Primitive("clear-input", "&optional input-stream")
3422    {
3423        public LispObject execute(LispObject[] args) throws ConditionThrowable
3424        {
3425            if (args.length > 1)
3426                signal(new WrongNumberOfArgumentsException(this));
3427            final Stream in;
3428            if (args.length == 0)
3429                in = checkCharacterInputStream(_STANDARD_INPUT_.symbolValue());
3430            else
3431                in = inSynonymOf(args[0]);
3432            in.clearInput();
3433            return NIL;
3434        }
3435    };
3436
3437    // ### %clear-output output-stream => nil
3438
// "If any of these operations does not make sense for output-stream, then
3439
// it does nothing."
3440
private static final Primitive1 _CLEAR_OUTPUT =
3441        new Primitive1("%clear-output", PACKAGE_SYS, false, "output-stream")
3442    {
3443        public LispObject execute(LispObject arg) throws ConditionThrowable
3444        {
3445            if (arg == T)
3446                return NIL; // *TERMINAL-IO*
3447
if (arg == NIL)
3448                return NIL; // *STANDARD-OUTPUT*
3449
if (arg instanceof Stream) {
3450                Stream stream = (Stream) arg;
3451                if (stream instanceof TwoWayStream) {
3452                    Stream out = ((TwoWayStream)stream).getOutputStream();
3453                    if (out.isOutputStream())
3454                        return NIL;
3455                }
3456                if (stream.isOutputStream())
3457                    return NIL;
3458            }
3459            return signal(new TypeError(arg, "output stream"));
3460        }
3461    };
3462
3463    // ### close
3464
// close stream &key abort => result
3465
private static final Primitive CLOSE =
3466        new Primitive("close", "stream &key abort")
3467    {
3468        public LispObject execute(LispObject[] args) throws ConditionThrowable
3469        {
3470            final int length = args.length;
3471            if (length == 0)
3472                signal(new WrongNumberOfArgumentsException(this));
3473            LispObject abort = NIL; // Default.
3474
Stream stream = checkStream(args[0]);
3475            if (length > 1) {
3476                if ((length - 1) % 2 != 0)
3477                    signal(new ProgramError("Odd number of keyword arguments."));
3478                if (length > 3)
3479                    signal(new WrongNumberOfArgumentsException(this));
3480                if (args[1] == Keyword.ABORT)
3481                    abort = args[2];
3482                else
3483                    signal(new ProgramError("Unrecognized keyword argument " +
3484                                            args[1].writeToString() + "."));
3485            }
3486            return stream.close(abort);
3487        }
3488    };
3489
3490    // ### multiple-value-list
3491
// multiple-value-list form => list
3492
// Evaluates form and creates a list of the multiple values it returns.
3493
// Should be a macro.
3494
private static final SpecialOperator MULTIPLE_VALUE_LIST =
3495        new SpecialOperator("multiple-value-list", "value-form")
3496    {
3497        public LispObject execute(LispObject args, Environment env)
3498            throws ConditionThrowable
3499        {
3500            if (args.length() != 1)
3501                signal(new WrongNumberOfArgumentsException(this));
3502            final LispThread thread = LispThread.currentThread();
3503            LispObject result = eval(args.car(), env, thread);
3504            LispObject[] values = thread.getValues();
3505            if (values == null)
3506                return new Cons(result);
3507            thread.clearValues();
3508            LispObject list = NIL;
3509            for (int i = values.length; i-- > 0;)
3510                list = new Cons(values[i], list);
3511            return list;
3512        }
3513    };
3514
3515    // ### nth-value
3516
// nth-value n form => object
3517
// Evaluates n and then form and returns the nth value returned by form, or
3518
// NIL if n >= number of values returned.
3519
// Should be a macro.
3520
private static final SpecialOperator NTH_VALUE =
3521        new SpecialOperator("nth-value", "n form")
3522    {
3523        public LispObject execute(LispObject args, Environment env)
3524            throws ConditionThrowable
3525        {
3526            if (args.length() != 2)
3527                signal(new WrongNumberOfArgumentsException(this));
3528            final LispThread thread = LispThread.currentThread();
3529            int n = Fixnum.getInt(eval(args.car(), env, thread));
3530            if (n < 0)
3531                n = 0;
3532            LispObject result = eval(args.cadr(), env, thread);
3533            LispObject[] values = thread.getValues();
3534            thread.clearValues();
3535            if (values == null) {
3536                // A single value was returned.
3537
return n == 0 ? result : NIL;
3538            }
3539            if (n < values.length)
3540                return values[n];
3541            return NIL;
3542        }
3543    };
3544
3545    // ### write-8-bits
3546
// write-8-bits byte stream => byte
3547
private static final Primitive2 WRITE_8_BITS =
3548        new Primitive2("write-8-bits", PACKAGE_SYS, false, "byte stream")
3549    {
3550        public LispObject execute (LispObject first, LispObject second)
3551            throws ConditionThrowable
3552        {
3553            int n;
3554            try {
3555                n = ((Fixnum)first).value;
3556            }
3557            catch (ClassCastException JavaDoc e) {
3558                return signal(new TypeError(first, Symbol.FIXNUM));
3559            }
3560            if (n < 0 || n > 255)
3561                signal(new TypeError(first,
3562                                     list2(Symbol.UNSIGNED_BYTE, new Fixnum(8))));
3563            checkBinaryOutputStream(second)._writeByte(n);
3564            return first;
3565        }
3566    };
3567
3568    // ### read-8-bits
3569
// read-8-bits stream &optional eof-error-p eof-value => byte
3570
private static final Primitive READ_8_BITS =
3571        new Primitive("read-8-bits", PACKAGE_SYS, false,
3572                      "stream &optional eof-error-p eof-value")
3573    {
3574        public LispObject execute (LispObject[] args) throws ConditionThrowable
3575        {
3576            int length = args.length;
3577            if (length < 1 || length > 3)
3578                signal(new WrongNumberOfArgumentsException(this));
3579            final Stream in = checkBinaryInputStream(args[0]);
3580            boolean eofError = length > 1 ? (args[1] != NIL) : true;
3581            LispObject eofValue = length > 2 ? args[2] : NIL;
3582            return in.readByte(eofError, eofValue);
3583        }
3584    };
3585
3586    // ### read-line
3587
// read-line &optional input-stream eof-error-p eof-value recursive-p
3588
// => line, missing-newline-p
3589
private static final Primitive READ_LINE =
3590        new Primitive("read-line",
3591                      "&optional input-stream eof-error-p eof-value recursive-p")
3592    {
3593        public LispObject execute(LispObject[] args) throws ConditionThrowable
3594        {
3595            int length = args.length;
3596            if (length > 4)
3597                signal(new WrongNumberOfArgumentsException(this));
3598            Stream stream =
3599                length > 0 ? inSynonymOf(args[0]) : getStandardInput();
3600            boolean eofError = length > 1 ? (args[1] != NIL) : true;
3601            LispObject eofValue = length > 2 ? args[2] : NIL;
3602            boolean recursive = length > 3 ? (args[3] != NIL) : false;
3603            return stream.readLine(eofError, eofValue);
3604        }
3605    };
3606
3607    // ### %read-from-string
3608
// read-from-string string &optional eof-error-p eof-value &key start end
3609
// preserve-whitespace => object, position
3610
private static final Primitive _READ_FROM_STRING =
3611        new Primitive("%read-from-string", PACKAGE_SYS, false)
3612    {
3613        public LispObject execute(LispObject[] args) throws ConditionThrowable
3614        {
3615            if (args.length < 6)
3616                signal(new WrongNumberOfArgumentsException(this));
3617            String JavaDoc s = args[0].getStringValue();
3618            boolean eofError = args[1] != NIL;
3619            LispObject eofValue = args[2];
3620            LispObject start = args[3];
3621            LispObject end = args[4];
3622            boolean preserveWhitespace = args[5] != NIL;
3623            int startIndex, endIndex;
3624            if (start != NIL)
3625                startIndex = (int) Fixnum.getValue(start);
3626            else
3627                startIndex = 0;
3628            if (end != NIL)
3629                endIndex = (int) Fixnum.getValue(end);
3630            else
3631                endIndex = s.length();
3632            StringInputStream in =
3633                new StringInputStream(s, startIndex, endIndex);
3634            LispObject result;
3635            if (preserveWhitespace)
3636                result = in.readPreservingWhitespace(eofError, eofValue, false);
3637            else
3638                result = in.read(eofError, eofValue, false);
3639            return LispThread.currentThread().setValues(result,
3640                                                        new Fixnum(in.getOffset()));
3641        }
3642    };
3643
3644    private static final Primitive1 _CALL_COUNT =
3645        new Primitive1("%call-count", PACKAGE_SYS, false)
3646    {
3647        public LispObject execute(LispObject arg) throws ConditionThrowable
3648        {
3649            return new Fixnum(arg.getCallCount());
3650        }
3651    };
3652
3653    private static final Primitive2 _SET_CALL_COUNT =
3654        new Primitive2("%set-call-count", PACKAGE_SYS, false)
3655    {
3656        public LispObject execute(LispObject first, LispObject second)
3657            throws ConditionThrowable
3658        {
3659            first.setCallCount(Fixnum.getValue(second));
3660            return second;
3661        }
3662    };
3663
3664    // ### read
3665
// read &optional input-stream eof-error-p eof-value recursive-p => object
3666
private static final Primitive READ =
3667        new Primitive("read",
3668                      "&optional input-stream eof-error-p eof-value recursive-p")
3669    {
3670        public LispObject execute(LispObject[] args) throws ConditionThrowable
3671        {
3672            int length = args.length;
3673            if (length > 4)
3674                signal(new WrongNumberOfArgumentsException(this));
3675            Stream stream =
3676                length > 0 ? checkCharacterInputStream(args[0]) : getStandardInput();
3677            boolean eofError = length > 1 ? (args[1] != NIL) : true;
3678            LispObject eofValue = length > 2 ? args[2] : NIL;
3679            boolean recursive = length > 3 ? (args[3] != NIL) : false;
3680            return stream.read(eofError, eofValue, recursive);
3681        }
3682    };
3683
3684    // ### read-preserving-whitespace
3685
// read &optional input-stream eof-error-p eof-value recursive-p => object
3686
private static final Primitive READ_PRESERVING_WHITESPACE =
3687        new Primitive("read-preserving-whitespace",
3688                      "&optional input-stream eof-error-p eof-value recursive-p")
3689    {
3690        public LispObject execute(LispObject[] args) throws ConditionThrowable
3691        {
3692            int length = args.length;
3693            if (length > 4)
3694                signal(new WrongNumberOfArgumentsException(this));
3695            Stream stream =
3696                length > 0 ? checkCharacterInputStream(args[0]) : getStandardInput();
3697            boolean eofError = length > 1 ? (args[1] != NIL) : true;
3698            LispObject eofValue = length > 2 ? args[2] : NIL;
3699            boolean recursive = length > 3 ? (args[3] != NIL) : false;
3700            return stream.readPreservingWhitespace(eofError, eofValue, recursive);
3701        }
3702    };
3703
3704    // ### read-char
3705
// read-char &optional input-stream eof-error-p eof-value recursive-p => char
3706
private static final Primitive READ_CHAR =
3707        new Primitive("read-char",
3708                      "&optional input-stream eof-error-p eof-value recursive-p")
3709    {
3710        public LispObject execute(LispObject[] args) throws ConditionThrowable
3711        {
3712            int length = args.length;
3713            if (length > 4)
3714                signal(new WrongNumberOfArgumentsException(this));
3715            Stream stream =
3716                length > 0 ? inSynonymOf(args[0]) : getStandardInput();
3717            boolean eofError = length > 1 ? (args[1] != NIL) : true;
3718            LispObject eofValue = length > 2 ? args[2] : NIL;
3719            boolean recursive = length > 3 ? (args[3] != NIL) : false;
3720            return stream.readChar(eofError, eofValue);
3721        }
3722    };
3723
3724    // ### unread-char
3725
// unread-char character &optional input-stream => nil
3726
private static final Primitive UNREAD_CHAR =
3727        new Primitive("unread-char", "character &optional input-stream")
3728    {
3729        public LispObject execute(LispObject arg) throws ConditionThrowable
3730        {
3731            return getStandardInput().unreadChar(checkCharacter(arg));
3732        }
3733        public LispObject execute(LispObject first, LispObject second)
3734            throws ConditionThrowable
3735        {
3736            Stream stream = inSynonymOf(second);
3737            return stream.unreadChar(checkCharacter(first));
3738        }
3739    };
3740
3741    // ### %set-lambda-name
3742
private static final Primitive2 _SET_LAMBDA_NAME =
3743        new Primitive2("%set-lambda-name", PACKAGE_SYS, false)
3744    {
3745        public LispObject execute(LispObject first, LispObject second)
3746            throws ConditionThrowable
3747        {
3748            if (first instanceof Function) {
3749                Function f = (Function) first;
3750                f.setLambdaName(second);
3751                return second;
3752            }
3753            return signal(new TypeError(first, "function"));
3754        }
3755    };
3756
3757    // ### shrink-vector
3758
// Destructively alters the vector, changing its length to NEW-SIZE, which
3759
// must be less than or equal to its current length.
3760
// shrink-vector vector new-size => vector
3761
private static final Primitive2 SHRINK_VECTOR =
3762        new Primitive2("shrink-vector", PACKAGE_SYS, false)
3763    {
3764        public LispObject execute(LispObject first, LispObject second)
3765            throws ConditionThrowable
3766        {
3767            checkVector(first).shrink(Fixnum.getInt(second));
3768            return first;
3769        }
3770    };
3771
3772    // ### subseq
3773
// subseq sequence start &optional end
3774
private static final Primitive SUBSEQ =
3775        new Primitive("subseq", "sequence start &optional end")
3776    {
3777        public LispObject execute(LispObject first, LispObject second)
3778            throws ConditionThrowable
3779        {
3780            final int start = Fixnum.getValue(second);
3781            if (start < 0) {
3782                StringBuffer JavaDoc sb = new StringBuffer JavaDoc("Bad start index (");
3783                sb.append(start);
3784                sb.append(") for SUBSEQ.");
3785                signal(new TypeError(sb.toString()));
3786            }
3787            if (first.listp())
3788                return list_subseq(first, start, -1);
3789            if (first.vectorp()) {
3790                AbstractVector v = (AbstractVector) first;
3791                return v.subseq(start, v.length());
3792            }
3793            return signal(new TypeError(first, Symbol.SEQUENCE));
3794        }
3795        public LispObject execute(LispObject first, LispObject second,
3796                                  LispObject third)
3797            throws ConditionThrowable
3798        {
3799            final int start = Fixnum.getValue(second);
3800            if (start < 0) {
3801                StringBuffer JavaDoc sb = new StringBuffer JavaDoc("Bad start index (");
3802                sb.append(start);
3803                sb.append(").");
3804                signal(new TypeError(sb.toString()));
3805            }
3806            int end;
3807            if (third != NIL) {
3808                end = Fixnum.getValue(third);
3809                if (start > end) {
3810                    StringBuffer JavaDoc sb = new StringBuffer JavaDoc("Start index (");
3811                    sb.append(start);
3812                    sb.append(") is greater than end index (");
3813                    sb.append(end);
3814                    sb.append(") for SUBSEQ.");
3815                    signal(new TypeError(sb.toString()));
3816                }
3817            } else
3818                end = -1;
3819            if (first.listp())
3820                return list_subseq(first, start, end);
3821            if (first.vectorp()) {
3822                AbstractVector v = (AbstractVector) first;
3823                if (end < 0)
3824                    end = v.length();
3825                return v.subseq(start, end);
3826            }
3827            return signal(new TypeError(first, Symbol.SEQUENCE));
3828        }
3829    };
3830
3831    private static final LispObject list_subseq(LispObject list, int start,
3832                                                int end)
3833        throws ConditionThrowable
3834    {
3835        int index = 0;
3836        LispObject result = NIL;
3837        while (list != NIL) {
3838            if (end >= 0 && index == end)
3839                return result.nreverse();
3840            if (index++ >= start)
3841                result = new Cons(list.car(), result);
3842            list = list.cdr();
3843        }
3844        return result.nreverse();
3845    }
3846
3847    // ### expt
3848
// expt base-number power-number => result
3849
public static final Primitive2 EXPT =
3850        new Primitive2("expt", "base-number power-number")
3851    {
3852        public LispObject execute(LispObject base, LispObject power)
3853            throws ConditionThrowable
3854        {
3855            if (power.zerop()) {
3856                if (power instanceof Fixnum) {
3857                    if (base instanceof LispFloat)
3858                        return LispFloat.ONE;
3859                    if (base instanceof Complex) {
3860                        if (((Complex)base).getRealPart() instanceof LispFloat)
3861                            return Complex.getInstance(LispFloat.ONE,
3862                                                       LispFloat.ZERO);
3863                    }
3864                    return Fixnum.ONE;
3865                }
3866                if (power instanceof LispFloat) {
3867                    return LispFloat.ONE;
3868                }
3869            }
3870            if (power instanceof Fixnum) {
3871                if (base.rationalp())
3872                    return intexp(base, power);
3873                LispObject result;
3874                if (base instanceof LispFloat)
3875                    result = LispFloat.ONE;
3876                else
3877                    result = Fixnum.ONE;
3878                int pow = ((Fixnum)power).value;
3879                if (pow > 0) {
3880                    for (int i = pow; i-- > 0;)
3881                        result = result.multiplyBy(base);
3882                } else if (pow < 0) {
3883                    for (int i = -pow; i-- > 0;)
3884                        result = result.divideBy(base);
3885                }
3886                return result;
3887            }
3888            if (power instanceof LispFloat) {
3889                if (base instanceof Fixnum) {
3890                    double d = Math.pow(((Fixnum)base).value,
3891                                        ((LispFloat)power).value);
3892                    return new LispFloat(d);
3893                }
3894                if (base instanceof LispFloat) {
3895                    double d = Math.pow(((LispFloat)base).value,
3896                                        ((LispFloat)power).value);
3897                    return new LispFloat(d);
3898                }
3899            }
3900            if (power instanceof Ratio) {
3901                if (base instanceof Fixnum) {
3902                    double d = Math.pow(((Fixnum)base).getValue(),
3903                                        ((Ratio)power).floatValue());
3904                    return new LispFloat(d);
3905                }
3906                if (base instanceof LispFloat) {
3907                    double d = Math.pow(((LispFloat)base).value,
3908                                        ((Ratio)power).floatValue());
3909                    return new LispFloat(d);
3910                }
3911            }
3912            signal(new LispError("EXPT: unsupported case"));
3913            return NIL;
3914        }
3915    };
3916
3917    // Adapted from SBCL.
3918
private static final LispObject intexp(LispObject base, LispObject power)
3919        throws ConditionThrowable
3920    {
3921        if (power.minusp()) {
3922            power = Fixnum.ZERO.subtract(power);
3923            return Fixnum.ONE.divideBy(intexp(base, power));
3924        }
3925        if (base.eql(Fixnum.TWO))
3926            return Fixnum.ONE.ash(power);
3927        LispObject nextn = power.ash(Fixnum.MINUS_ONE);
3928        LispObject total;
3929        if (power.oddp())
3930            total = base;
3931        else
3932            total = Fixnum.ONE;
3933        while (true) {
3934            if (nextn.zerop())
3935                return total;
3936            base = base.multiplyBy(base);
3937            power = nextn;
3938            nextn = power.ash(Fixnum.MINUS_ONE);
3939            if (power.oddp())
3940                total = base.multiplyBy(total);
3941        }
3942    }
3943
3944    // ### list
3945
private static final Primitive LIST = new Primitive("list", "&rest objects")
3946    {
3947        public LispObject execute(LispObject arg) throws ConditionThrowable
3948        {
3949            return new Cons(arg);
3950        }
3951        public LispObject execute(LispObject first, LispObject second)
3952            throws ConditionThrowable
3953        {
3954            return new Cons(first, new Cons(second));
3955        }
3956        public LispObject execute(LispObject first, LispObject second,
3957            LispObject third) throws ConditionThrowable
3958        {
3959            return new Cons(first, new Cons(second, new Cons(third)));
3960        }
3961        public LispObject execute(LispObject[] args) throws ConditionThrowable
3962        {
3963            LispObject result = NIL;
3964            for (int i = args.length; i-- > 0;)
3965                result = new Cons(args[i], result);
3966            return result;
3967        }
3968    };
3969
3970    // ### list*
3971
private static final Primitive LIST_ = new Primitive("list*", "&rest objects")
3972    {
3973        public LispObject execute() throws ConditionThrowable
3974        {
3975            signal(new WrongNumberOfArgumentsException("LIST*"));
3976            return NIL;
3977        }
3978        public LispObject execute(LispObject arg) throws ConditionThrowable
3979        {
3980            return arg;
3981        }
3982        public LispObject execute(LispObject first, LispObject second)
3983            throws ConditionThrowable
3984        {
3985            return new Cons(first, second);
3986        }
3987        public LispObject execute(LispObject first, LispObject second,
3988                                  LispObject third) throws ConditionThrowable
3989        {
3990            return new Cons(first, new Cons(second, third));
3991        }
3992        public LispObject execute(LispObject[] args) throws ConditionThrowable
3993        {
3994            int i = args.length - 1;
3995            LispObject result = args[i];
3996            while (i-- > 0)
3997                result = new Cons(args[i], result);
3998            return result;
3999        }
4000    };
4001
4002    // ### nreverse
4003
public static final Primitive1 NREVERSE = new Primitive1("nreverse", "sequence")
4004    {
4005        public LispObject execute (LispObject arg) throws ConditionThrowable
4006        {
4007            return arg.nreverse();
4008        }
4009    };
4010
4011    // ### nreconc
4012
// Adapted from CLISP.
4013
private static final Primitive2 NRECONC = new Primitive2("nreconc", "list tail")
4014    {
4015        public LispObject execute(LispObject list, LispObject obj)
4016            throws ConditionThrowable
4017        {
4018            if (list instanceof Cons) {
4019                LispObject list3 = list.cdr();
4020                if (list3 instanceof Cons) {
4021                    if (list3.cdr() instanceof Cons) {
4022                        LispObject list1 = list3;
4023                        LispObject list2 = NIL;
4024                        do {
4025                            LispObject h = list3.cdr();
4026                            list3.setCdr(list2);
4027                            list2 = list3;
4028                            list3 = h;
4029                        } while (list3.cdr() instanceof Cons);
4030                        list.setCdr(list2);
4031                        list1.setCdr(list3);
4032                    }
4033                    LispObject h = list.car();
4034                    list.setCar(list3.car());
4035                    list3.setCar(h);
4036                    list3.setCdr(obj);
4037                } else if (list3 == NIL) {
4038                    list.setCdr(obj);
4039                } else
4040                    signal(new TypeError(list3, Symbol.LIST));
4041                return list;
4042            } else
4043                return obj;
4044        }
4045    };
4046
4047    // ### reverse
4048
private static final Primitive1 REVERSE = new Primitive1("reverse", "sequence")
4049    {
4050        public LispObject execute(LispObject arg) throws ConditionThrowable
4051        {
4052            if (arg instanceof AbstractVector)
4053                return ((AbstractVector)arg).reverse();
4054            if (arg instanceof Cons) {
4055                LispObject result = NIL;
4056                while (arg != NIL) {
4057                    result = new Cons(arg.car(), result);
4058                    arg = arg.cdr();
4059                }
4060                return result;
4061            }
4062            if (arg == NIL)
4063                return NIL;
4064            signal(new TypeError(arg, "proper sequence"));
4065            return NIL;
4066        }
4067    };
4068
4069    // ### %set-elt
4070
// %setelt sequence index newval => newval
4071
private static final Primitive3 _SET_ELT =
4072        new Primitive3("%set-elt", PACKAGE_SYS, false)
4073    {
4074        public LispObject execute(LispObject first, LispObject second,
4075                                  LispObject third)
4076            throws ConditionThrowable
4077        {
4078            if (first instanceof AbstractVector) {
4079                ((AbstractVector)first).setRowMajor(Fixnum.getValue(second), third);
4080                return third;
4081            }
4082            if (first instanceof Cons) {
4083                int index = Fixnum.getValue(second);
4084                if (index < 0)
4085                    signal(new TypeError());
4086                LispObject list = first;
4087                int i = 0;
4088                while (true) {
4089                    if (i == index) {
4090                        list.setCar(third);
4091                        return third;
4092                    }
4093                    list = list.cdr();
4094                    if (list == NIL)
4095                        signal(new TypeError());
4096                    ++i;
4097                }
4098            }
4099            signal(new TypeError(first, Symbol.SEQUENCE));
4100            return NIL;
4101        }
4102    };
4103
4104// (defun maptree (fun x)
4105
// (if (atom x)
4106
// (funcall fun x)
4107
// (let ((a (funcall fun (car x)))
4108
// (d (maptree fun (cdr x))))
4109
// (if (and (eql a (car x)) (eql d (cdr x)))
4110
// x
4111
// (cons a d)))))
4112

4113    // ### maptree
4114
private static final Primitive2 MAPTREE =
4115        new Primitive2("maptree", PACKAGE_SYS, false)
4116    {
4117        public LispObject execute(LispObject fun, LispObject x)
4118            throws ConditionThrowable
4119        {
4120            if (x instanceof Cons) {
4121                LispObject a = fun.execute(x.car());
4122                // Recurse!
4123
LispObject d = execute(fun, x.cdr());
4124                if (a.eql(x.car()) && d.eql(x.cdr()))
4125                    return x;
4126                else
4127                    return new Cons(a, d);
4128            } else
4129                return fun.execute(x);
4130        }
4131    };
4132
4133    // ### %make-list
4134
private static final Primitive2 _MAKE_LIST =
4135        new Primitive2("%make-list", PACKAGE_SYS, false) {
4136        public LispObject execute(LispObject first, LispObject second)
4137            throws ConditionThrowable
4138        {
4139            int size = Fixnum.getValue(first);
4140            if (size < 0)
4141                signal(new TypeError(String.valueOf(size) +
4142                                     " is not a valid list length."));
4143            LispObject result = NIL;
4144            for (int i = size; i-- > 0;)
4145                result = new Cons(second, result);
4146            return result;
4147        }
4148    };
4149
4150    // ### %member
4151
// %member item list key test test-not => tail
4152
private static final Primitive _MEMBER =
4153        new Primitive("%member", PACKAGE_SYS, false) {
4154        public LispObject execute(LispObject[] args) throws ConditionThrowable
4155        {
4156            if (args.length != 5)
4157                signal(new WrongNumberOfArgumentsException(this));
4158            LispObject item = args[0];
4159            LispObject tail = checkList(args[1]);
4160            LispObject key = args[2];
4161            if (key != NIL) {
4162                if (key instanceof Symbol)
4163                    key = key.getSymbolFunction();
4164                if (!(key instanceof Function || key instanceof GenericFunction))
4165                    signal(new UndefinedFunction(args[2]));
4166            }
4167            LispObject test = args[3];
4168            LispObject testNot = args[4];
4169            if (test != NIL && testNot != NIL)
4170                signal(new LispError("MEMBER: test and test-not both supplied"));
4171            if (test == NIL && testNot == NIL) {
4172                test = EQL;
4173            } else if (test != NIL) {
4174                if (test instanceof Symbol)
4175                    test = test.getSymbolFunction();
4176                if (!(test instanceof Function || test instanceof GenericFunction))
4177                    signal(new UndefinedFunction(args[3]));
4178            } else if (testNot != NIL) {
4179                if (testNot instanceof Symbol)
4180                    testNot = testNot.getSymbolFunction();
4181                if (!(testNot instanceof Function || testNot instanceof GenericFunction))
4182                    signal(new UndefinedFunction(args[3]));
4183            }
4184            if (key == NIL && test == EQL) {
4185                while (tail != NIL) {
4186                    if (item.eql(tail.car()))
4187                        return tail;
4188                    tail = tail.cdr();
4189                }
4190                return NIL;
4191            }
4192            while (tail != NIL) {
4193                LispObject candidate = tail.car();
4194                if (key != NIL)
4195                    candidate = key.execute(candidate);
4196                if (test != NIL) {
4197                    if (test.execute(item, candidate) == T)
4198                        return tail;
4199                } else if (testNot != NIL) {
4200                    if (testNot.execute(item, candidate) == NIL)
4201                        return tail;
4202                }
4203                tail = tail.cdr();
4204            }
4205            return NIL;
4206        }
4207    };
4208
4209    // ### funcall-key
4210
// funcall-key function-or-nil element
4211
private static final Primitive2 FUNCALL_KEY =
4212        new Primitive2("funcall-key", PACKAGE_SYS, false) {
4213        public LispObject execute(LispObject first, LispObject second)
4214            throws ConditionThrowable
4215        {
4216            if (first != NIL)
4217                return funcall1(first, second, LispThread.currentThread());
4218            return second;
4219        }
4220    };
4221
4222    // ### coerce-to-function
4223
private static final Primitive1 COERCE_TO_FUNCTION =
4224        new Primitive1("coerce-to-function", PACKAGE_SYS, false)
4225    {
4226        public LispObject execute(LispObject arg) throws ConditionThrowable
4227        {
4228            return coerceToFunction(arg);
4229        }
4230    };
4231
4232    // ### make-closure lambda-form environment => closure
4233
private static final Primitive2 MAKE_CLOSURE =
4234        new Primitive2("make-closure", PACKAGE_SYS, false)
4235    {
4236        public LispObject execute(LispObject first, LispObject second)
4237            throws ConditionThrowable
4238        {
4239            if (first instanceof Cons && first.car() == Symbol.LAMBDA) {
4240                final Environment env;
4241                if (second == NIL)
4242                    env = new Environment();
4243                else
4244                    env = checkEnvironment(second);
4245                return new Closure(first.cadr(), first.cddr(), env);
4246            }
4247            return signal(new TypeError("Argument to MAKE-CLOSURE is not a lambda form."));
4248        }
4249    };
4250
4251    // ### streamp
4252
private static final Primitive1 STREAMP = new Primitive1("streamp", "object")
4253    {
4254        public LispObject execute(LispObject arg)
4255        {
4256            return arg instanceof Stream ? T : NIL;
4257        }
4258    };
4259
4260    // ### integerp
4261
private static final Primitive1 INTEGERP = new Primitive1("integerp", "object")
4262    {
4263        public LispObject execute(LispObject arg)
4264        {
4265            return arg.INTEGERP();
4266        }
4267    };
4268
4269    // ### evenp
4270
private static final Primitive1 EVENP = new Primitive1("evenp", "integer")
4271    {
4272        public LispObject execute(LispObject arg) throws ConditionThrowable
4273        {
4274            return arg.EVENP();
4275        }
4276    };
4277
4278    // ### oddp
4279
private static final Primitive1 ODDP = new Primitive1("oddp", "integer")
4280    {
4281        public LispObject execute(LispObject arg) throws ConditionThrowable
4282        {
4283            return arg.ODDP();
4284        }
4285    };
4286
4287    // ### numberp
4288
private static final Primitive1 NUMBERP = new Primitive1("numberp", "object")
4289    {
4290        public LispObject execute(LispObject arg)
4291        {
4292            return arg.NUMBERP();
4293        }
4294    };
4295
4296    // ### realp
4297
private static final Primitive1 REALP = new Primitive1("realp", "object")
4298    {
4299        public LispObject execute(LispObject arg)
4300        {
4301            return arg.REALP();
4302        }
4303    };
4304
4305    // ### rationalp
4306
private static final Primitive1 RATIONALP = new Primitive1("rationalp","object") {
4307        public LispObject execute(LispObject arg)
4308        {
4309            return arg.RATIONALP();
4310        }
4311    };
4312
4313    // ### complex
4314
private static final Primitive2 COMPLEX = new Primitive2("complex","realpart &optional imagpart") {
4315        public LispObject execute(LispObject arg) throws ConditionThrowable
4316        {
4317            if (arg instanceof LispFloat)
4318                return Complex.getInstance(arg, LispFloat.ZERO);
4319            if (arg.realp())
4320                return arg;
4321            signal(new TypeError(arg, "real number"));
4322            return NIL;
4323        }
4324        public LispObject execute(LispObject first, LispObject second)
4325            throws ConditionThrowable
4326        {
4327            return Complex.getInstance(first, second);
4328        }
4329    };
4330
4331    // ### complexp
4332
private static final Primitive1 COMPLEXP = new Primitive1("complexp","object") {
4333        public LispObject execute(LispObject arg)
4334        {
4335            return arg.COMPLEXP();
4336        }
4337    };
4338
4339    // ### numerator
4340
private static final Primitive1 NUMERATOR = new Primitive1("numerator","rational") {
4341        public LispObject execute(LispObject arg) throws ConditionThrowable
4342        {
4343            return arg.NUMERATOR();
4344        }
4345    };
4346
4347    // ### denominator
4348
private static final Primitive1 DENOMINATOR = new Primitive1("denominator","rational")
4349    {
4350        public LispObject execute(LispObject arg) throws ConditionThrowable
4351        {
4352            return arg.DENOMINATOR();
4353        }
4354    };
4355
4356    // ### realpart
4357
private static final Primitive1 REALPART = new Primitive1("realpart","number")
4358    {
4359        public LispObject execute(LispObject arg) throws ConditionThrowable
4360        {
4361            if (arg instanceof Complex)
4362                return ((Complex)arg).getRealPart();
4363            if (arg.numberp())
4364                return arg;
4365            signal(new TypeError(arg, "number"));
4366            return NIL;
4367        }
4368    };
4369
4370    // ### imagpart
4371
private static final Primitive1 IMAGPART = new Primitive1("imagpart", "number")
4372    {
4373        public LispObject execute(LispObject arg) throws ConditionThrowable
4374        {
4375            if (arg instanceof Complex)
4376                return ((Complex)arg).getImaginaryPart();
4377            return arg.multiplyBy(Fixnum.ZERO);
4378        }
4379    };
4380
4381    // ### integer-length
4382
private static final Primitive1 INTEGER_LENGTH =
4383        new Primitive1("integer-length", "integer")
4384    {
4385        public LispObject execute(LispObject arg) throws ConditionThrowable
4386        {
4387            if (arg instanceof Fixnum) {
4388                int n = ((Fixnum)arg).value;
4389                if (n < 0)
4390                    n = ~n;
4391                int count = 0;
4392                while (n > 0) {
4393                    n = n >>> 1;
4394                    ++count;
4395                }
4396                return new Fixnum(count);
4397            }
4398            if (arg instanceof Bignum)
4399                return new Fixnum(((Bignum)arg).value.bitLength());
4400            return signal(new TypeError(arg, "integer"));
4401        }
4402    };
4403
4404    // ### gcd-2
4405
private static final Primitive2 GCD_2 =
4406        new Primitive2("gcd-2", PACKAGE_SYS, false)
4407    {
4408        public LispObject execute(LispObject first, LispObject second)
4409            throws ConditionThrowable
4410        {
4411            BigInteger JavaDoc n1, n2;
4412            if (first instanceof Fixnum)
4413                n1 = BigInteger.valueOf(((Fixnum)first).getValue());
4414            else if (first instanceof Bignum)
4415                n1 = ((Bignum)first).getValue();
4416            else {
4417                signal(new TypeError(first, "integer"));
4418                return NIL;
4419            }
4420            if (second instanceof Fixnum)
4421                n2 = BigInteger.valueOf(((Fixnum)second).getValue());
4422            else if (second instanceof Bignum)
4423                n2 = ((Bignum)second).getValue();
4424            else {
4425                signal(new TypeError(second, "integer"));
4426                return NIL;
4427            }
4428            return number(n1.gcd(n2));
4429        }
4430    };
4431
4432    // ### identity-hash-code
4433
private static final Primitive1 IDENTITY_HASH_CODE =
4434        new Primitive1("identity-hash-code", PACKAGE_SYS, false)
4435    {
4436        public LispObject execute(LispObject arg) throws ConditionThrowable
4437        {
4438            return new Fixnum(System.identityHashCode(arg));
4439        }
4440    };
4441
4442    // ### simple-vector-search pattern vector => position
4443
// Searches vector for pattern.
4444
private static final Primitive2 SIMPLE_VECTOR_SEARCH =
4445        new Primitive2("simple-vector-search", PACKAGE_SYS, false)
4446    {
4447        public LispObject execute(LispObject first, LispObject second)
4448            throws ConditionThrowable
4449        {
4450            AbstractVector v = checkVector(second);
4451            if (first.length() == 0)
4452                return Fixnum.ZERO;
4453            final int patternLength = first.length();
4454            final int limit = v.length() - patternLength;
4455            if (first instanceof AbstractVector) {
4456                AbstractVector pattern = (AbstractVector) first;
4457                LispObject element = pattern.getRowMajor(0);
4458                for (int i = 0; i <= limit; i++) {
4459                    if (v.getRowMajor(i).eql(element)) {
4460                        // Found match for first element of pattern.
4461
boolean match = true;
4462                        // We've already checked the first element.
4463
int j = i + 1;
4464                        for (int k = 1; k < patternLength; k++) {
4465                            if (v.getRowMajor(j).eql(pattern.getRowMajor(k))) {
4466                                ++j;
4467                            } else {
4468                                match = false;
4469                                break;
4470                            }
4471                        }
4472                        if (match)
4473                            return new Fixnum(i);
4474                    }
4475                }
4476            } else {
4477                // Pattern is a list.
4478
LispObject element = first.car();
4479                for (int i = 0; i <= limit; i++) {
4480                    if (v.getRowMajor(i).eql(element)) {
4481                        // Found match for first element of pattern.
4482
boolean match = true;
4483                        // We've already checked the first element.
4484
int j = i + 1;
4485                        for (LispObject rest = first.cdr(); rest != NIL; rest = rest.cdr()) {
4486                            if (v.getRowMajor(j).eql(rest.car())) {
4487                                ++j;
4488                            } else {
4489                                match = false;
4490                                break;
4491                            }
4492                        }
4493                        if (match)
4494                            return new Fixnum(i);
4495                    }
4496                }
4497            }
4498            return NIL;
4499        }
4500    };
4501
4502    // ### uptime
4503
private static final Primitive0 UPTIME =
4504        new Primitive0("uptime", PACKAGE_EXT, true)
4505    {
4506        public LispObject execute() throws ConditionThrowable
4507        {
4508            return number(System.currentTimeMillis() - Main.startTimeMillis);
4509        }
4510    };
4511
4512    // ### built-in-function-p
4513
private static final Primitive1 BUILT_IN_FUNCTION_P =
4514        new Primitive1("built-in-function-p", PACKAGE_SYS, false)
4515    {
4516        public LispObject execute(LispObject arg) throws ConditionThrowable
4517        {
4518            try {
4519                return ((Symbol)arg).isBuiltInFunction() ? T : NIL;
4520            }
4521            catch (ClassCastException JavaDoc e) {
4522                return signal(new TypeError(arg, Symbol.SYMBOL));
4523            }
4524        }
4525    };
4526
4527    // ### inspected-parts
4528
private static final Primitive1 INSPECTED_PARTS =
4529        new Primitive1("inspected-parts", PACKAGE_SYS, false)
4530    {
4531        public LispObject execute(LispObject arg) throws ConditionThrowable
4532        {
4533            return arg.getParts();
4534        }
4535    };
4536
4537    // ### inspected-description
4538
private static final Primitive1 INSPECTED_DESCRIPTION =
4539        new Primitive1("inspected-description", PACKAGE_SYS, false)
4540    {
4541        public LispObject execute(LispObject arg) throws ConditionThrowable
4542        {
4543            return arg.getDescription();
4544        }
4545    };
4546
4547    static {
4548        new Primitives();
4549    }
4550}
4551
Popular Tags