source: branches/0.16.x/abcl/src/org/armedbear/lisp/Primitives.java

Last change on this file was 12079, checked in by ehuelsmann, 16 years ago

Add API to execute()-able classes for hot spot profiling
next to normal stack profiling.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 165.1 KB
Line 
1/*
2 * Primitives.java
3 *
4 * Copyright (C) 2002-2007 Peter Graves
5 * $Id: Primitives.java 12079 2009-07-31 19:45:54Z ehuelsmann $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36import java.math.BigInteger;
37import java.util.ArrayList;
38
39public final class Primitives extends Lisp
40{
41  // ### *
42  public static final Primitive MULTIPLY =
43    new Primitive(Symbol.STAR, "&rest numbers")
44    {
45      @Override
46      public LispObject execute()
47      {
48        return Fixnum.ONE;
49      }
50      @Override
51      public LispObject execute(LispObject arg) throws ConditionThrowable
52      {
53        if (arg.numberp())
54          return arg;
55        return type_error(arg, Symbol.NUMBER);
56      }
57      @Override
58      public LispObject execute(LispObject first, LispObject second)
59        throws ConditionThrowable
60      {
61        return first.multiplyBy(second);
62      }
63      @Override
64      public LispObject execute(LispObject[] args) throws ConditionThrowable
65      {
66        LispObject result = Fixnum.ONE;
67        for (int i = 0; i < args.length; i++)
68          result = result.multiplyBy(args[i]);
69        return result;
70      }
71    };
72
73  // ### /
74  public static final Primitive DIVIDE =
75    new Primitive(Symbol.SLASH, "numerator &rest denominators")
76    {
77      @Override
78      public LispObject execute() throws ConditionThrowable
79      {
80        return error(new WrongNumberOfArgumentsException(this));
81      }
82      @Override
83      public LispObject execute(LispObject arg) throws ConditionThrowable
84      {
85        return Fixnum.ONE.divideBy(arg);
86      }
87      @Override
88      public LispObject execute(LispObject first, LispObject second)
89        throws ConditionThrowable
90      {
91        return first.divideBy(second);
92      }
93      @Override
94      public LispObject execute(LispObject[] args) throws ConditionThrowable
95      {
96        LispObject result = args[0];
97        for (int i = 1; i < args.length; i++)
98          result = result.divideBy(args[i]);
99        return result;
100      }
101    };
102
103  // ### min
104  public static final Primitive MIN =
105    new Primitive(Symbol.MIN, "&rest reals")
106    {
107      @Override
108      public LispObject execute() throws ConditionThrowable
109      {
110        return error(new WrongNumberOfArgumentsException(this));
111      }
112      @Override
113      public LispObject execute(LispObject arg) throws ConditionThrowable
114      {
115        if (arg.realp())
116          return arg;
117        return type_error(arg, Symbol.REAL);
118      }
119      @Override
120      public LispObject execute(LispObject first, LispObject second)
121        throws ConditionThrowable
122      {
123        return first.isLessThan(second) ? first : second;
124      }
125      @Override
126      public LispObject execute(LispObject[] args) throws ConditionThrowable
127      {
128        LispObject result = args[0];
129        if (!result.realp())
130          type_error(result, Symbol.REAL);
131        for (int i = 1; i < args.length; i++)
132          {
133            if (args[i].isLessThan(result))
134              result = args[i];
135          }
136        return result;
137      }
138    };
139
140  // ### max
141  public static final Primitive MAX =
142    new Primitive(Symbol.MAX, "&rest reals")
143    {
144      @Override
145      public LispObject execute() throws ConditionThrowable
146      {
147        return error(new WrongNumberOfArgumentsException(this));
148      }
149      @Override
150      public LispObject execute(LispObject arg) throws ConditionThrowable
151      {
152        if (arg.realp())
153          return arg;
154        return type_error(arg, Symbol.REAL);
155      }
156      @Override
157      public LispObject execute(LispObject first, LispObject second)
158        throws ConditionThrowable
159      {
160        return first.isGreaterThan(second) ? first : second;
161      }
162      @Override
163      public LispObject execute(LispObject[] args) throws ConditionThrowable
164      {
165        LispObject result = args[0];
166        if (!result.realp())
167          type_error(result, Symbol.REAL);
168        for (int i = 1; i < args.length; i++)
169          {
170            if (args[i].isGreaterThan(result))
171              result = args[i];
172          }
173        return result;
174      }
175    };
176
177  // ### identity
178  private static final Primitive IDENTITY =
179    new Primitive(Symbol.IDENTITY, "object")
180    {
181      @Override
182      public LispObject execute(LispObject arg) throws ConditionThrowable
183      {
184        return arg;
185      }
186    };
187
188  // ### compiled-function-p
189  private static final Primitive COMPILED_FUNCTION_P =
190    new Primitive(Symbol.COMPILED_FUNCTION_P, "object")
191    {
192      @Override
193      public LispObject execute(LispObject arg) throws ConditionThrowable
194      {
195        return arg.typep(Symbol.COMPILED_FUNCTION);
196      }
197    };
198
199  // ### consp
200  private static final Primitive CONSP =
201    new Primitive(Symbol.CONSP, "object")
202    {
203      @Override
204      public LispObject execute(LispObject arg) throws ConditionThrowable
205      {
206        return arg instanceof Cons ? T : NIL;
207      }
208    };
209
210  // ### listp
211  private static final Primitive LISTP =
212    new Primitive(Symbol.LISTP, "object")
213    {
214      @Override
215      public LispObject execute(LispObject arg) throws ConditionThrowable
216      {
217        return arg.LISTP();
218      }
219    };
220
221  // ### abs
222  private static final Primitive ABS =
223    new Primitive(Symbol.ABS, "number")
224    {
225      @Override
226      public LispObject execute(LispObject arg) throws ConditionThrowable
227      {
228        return arg.ABS();
229      }
230    };
231
232  // ### arrayp
233  private static final Primitive ARRAYP =
234    new Primitive(Symbol.ARRAYP, "object")
235    {
236      @Override
237      public LispObject execute(LispObject arg) throws ConditionThrowable
238      {
239        return arg instanceof AbstractArray ? T : NIL;
240      }
241    };
242
243  // ### array-has-fill-pointer-p
244  private static final Primitive ARRAY_HAS_FILL_POINTER_P =
245    new Primitive(Symbol.ARRAY_HAS_FILL_POINTER_P, "array")
246    {
247      @Override
248      public LispObject execute(LispObject arg) throws ConditionThrowable
249      {
250            return checkArray(arg).hasFillPointer() ? T : NIL;
251          }
252    };
253
254  // ### vectorp
255  private static final Primitive VECTORP =
256    new Primitive(Symbol.VECTORP, "object")
257    {
258      @Override
259      public LispObject execute(LispObject arg) throws ConditionThrowable
260      {
261        return arg.VECTORP();
262      }
263    };
264
265  // ### simple-vector-p
266  private static final Primitive SIMPLE_VECTOR_P =
267    new Primitive(Symbol.SIMPLE_VECTOR_P, "object")
268    {
269      @Override
270      public LispObject execute(LispObject arg) throws ConditionThrowable
271      {
272        return arg instanceof SimpleVector ? T : NIL;
273      }
274    };
275
276  // ### bit-vector-p
277  private static final Primitive BIT_VECTOR_P =
278    new Primitive(Symbol.BIT_VECTOR_P, "object")
279    {
280      @Override
281      public LispObject execute(LispObject arg) throws ConditionThrowable
282      {
283        return arg instanceof AbstractBitVector ? T : NIL;
284      }
285    };
286
287  // ### simple-bit-vector-p
288  private static final Primitive SIMPLE_BIT_VECTOR_P =
289    new Primitive(Symbol.SIMPLE_BIT_VECTOR_P, "object")
290    {
291      @Override
292      public LispObject execute(LispObject arg) throws ConditionThrowable
293      {
294        return arg.typep(Symbol.SIMPLE_BIT_VECTOR);
295      }
296    };
297
298  // ### %eval
299  private static final Primitive _EVAL =
300    new Primitive("%eval", PACKAGE_SYS, false, "form")
301    {
302      @Override
303      public LispObject execute(LispObject arg) throws ConditionThrowable
304      {
305        return eval(arg, new Environment(), LispThread.currentThread());
306      }
307    };
308
309  // ### eq
310  private static final Primitive EQ = new Primitive(Symbol.EQ, "x y")
311    {
312      @Override
313      public LispObject execute(LispObject first, LispObject second)
314        throws ConditionThrowable
315      {
316        return first == second ? T : NIL;
317      }
318    };
319
320  // ### eql
321  private static final Primitive EQL = new Primitive(Symbol.EQL, "x y")
322    {
323      @Override
324      public LispObject execute(LispObject first, LispObject second)
325        throws ConditionThrowable
326      {
327        return first.eql(second) ? T : NIL;
328      }
329    };
330
331  // ### equal
332  private static final Primitive EQUAL = new Primitive(Symbol.EQUAL, "x y")
333    {
334      @Override
335      public LispObject execute(LispObject first, LispObject second)
336        throws ConditionThrowable
337      {
338        return first.equal(second) ? T : NIL;
339      }
340    };
341
342  // ### equalp
343  private static final Primitive EQUALP = new Primitive(Symbol.EQUALP, "x y")
344    {
345      @Override
346      public LispObject execute(LispObject first, LispObject second)
347        throws ConditionThrowable
348      {
349        return first.equalp(second) ? T : NIL;
350      }
351    };
352
353  // ### values
354  private static final Primitive VALUES =
355    new Primitive(Symbol.VALUES, "&rest object")
356    {
357      @Override
358      public LispObject execute()
359      {
360        return LispThread.currentThread().setValues();
361      }
362      @Override
363      public LispObject execute(LispObject arg)
364      {
365        return LispThread.currentThread().setValues(arg);
366      }
367      @Override
368      public LispObject execute(LispObject first, LispObject second)
369      {
370        return LispThread.currentThread().setValues(first, second);
371      }
372      @Override
373      public LispObject execute(LispObject first, LispObject second,
374                                LispObject third)
375      {
376        return LispThread.currentThread().setValues(first, second, third);
377      }
378      @Override
379      public LispObject execute(LispObject first, LispObject second,
380                                LispObject third, LispObject fourth)
381      {
382        return LispThread.currentThread().setValues(first, second, third,
383                                                    fourth);
384      }
385      @Override
386      public LispObject execute(LispObject[] args)
387      {
388        return LispThread.currentThread().setValues(args);
389      }
390    };
391
392  // ### values-list list => element*
393  // Returns the elements of the list as multiple values.
394  private static final Primitive VALUES_LIST =
395    new Primitive(Symbol.VALUES_LIST, "list")
396    {
397      @Override
398      public LispObject execute(LispObject arg) throws ConditionThrowable
399      {
400        if (arg == NIL)
401          return LispThread.currentThread().setValues();
402        if (arg.cdr() == NIL)
403          return arg.car();
404        return LispThread.currentThread().setValues(arg.copyToArray());
405      }
406    };
407
408  // ### cons
409  private static final Primitive CONS =
410    new Primitive(Symbol.CONS, "object-1 object-2")
411    {
412      @Override
413      public LispObject execute(LispObject first, LispObject second)
414        throws ConditionThrowable
415      {
416        return new Cons(first, second);
417      }
418    };
419
420  // ### length
421  private static final Primitive LENGTH =
422    new Primitive(Symbol.LENGTH, "sequence")
423    {
424      @Override
425      public LispObject execute(LispObject arg) throws ConditionThrowable
426      {
427        return arg.LENGTH();
428      }
429    };
430
431  // ### elt
432  private static final Primitive ELT =
433    new Primitive(Symbol.ELT, "sequence index")
434    {
435      @Override
436      public LispObject execute(LispObject first, LispObject second)
437        throws ConditionThrowable
438      {
439            return first.elt(Fixnum.getValue(second));
440      }
441    };
442
443  // ### atom
444  private static final Primitive ATOM = new Primitive(Symbol.ATOM, "object")
445    {
446      @Override
447      public LispObject execute(LispObject arg) throws ConditionThrowable
448      {
449        return arg instanceof Cons ? NIL : T;
450      }
451    };
452
453  // ### constantp
454  private static final Primitive CONSTANTP =
455    new Primitive(Symbol.CONSTANTP, "form &optional environment")
456    {
457      @Override
458      public LispObject execute(LispObject arg) throws ConditionThrowable
459      {
460        return arg.constantp() ? T : NIL;
461      }
462      @Override
463      public LispObject execute(LispObject first, LispObject second)
464        throws ConditionThrowable
465      {
466        return first.constantp() ? T : NIL;
467      }
468    };
469
470  // ### functionp
471  private static final Primitive FUNCTIONP =
472    new Primitive(Symbol.FUNCTIONP, "object")
473    {
474      @Override
475      public LispObject execute(LispObject arg) throws ConditionThrowable
476      {
477        return (arg instanceof Function || arg instanceof StandardGenericFunction) ? T : NIL;
478      }
479    };
480
481  // ### special-operator-p
482  private static final Primitive SPECIAL_OPERATOR_P =
483    new Primitive(Symbol.SPECIAL_OPERATOR_P, "symbol")
484    {
485      @Override
486      public LispObject execute(LispObject arg) throws ConditionThrowable
487      {
488        return arg.isSpecialOperator() ? T : NIL;
489      }
490    };
491
492  // ### symbolp
493  private static final Primitive SYMBOLP =
494    new Primitive(Symbol.SYMBOLP, "object")
495    {
496      @Override
497      public LispObject execute(LispObject arg) throws ConditionThrowable
498      {
499        return arg instanceof Symbol ? T : NIL;
500      }
501    };
502
503  // ### endp
504  private static final Primitive ENDP = new Primitive(Symbol.ENDP, "list")
505    {
506      @Override
507      public LispObject execute(LispObject arg) throws ConditionThrowable
508      {
509        return arg.endp() ? T : NIL;
510      }
511    };
512
513  // ### null
514  private static final Primitive NULL = new Primitive(Symbol.NULL, "object")
515    {
516      @Override
517      public LispObject execute(LispObject arg) throws ConditionThrowable
518      {
519        return arg == NIL ? T : NIL;
520      }
521    };
522
523  // ### not
524  private static final Primitive NOT = new Primitive(Symbol.NOT, "x")
525    {
526      @Override
527      public LispObject execute(LispObject arg) throws ConditionThrowable
528      {
529        return arg == NIL ? T : NIL;
530      }
531    };
532
533  // ### plusp
534  private static final Primitive PLUSP = new Primitive(Symbol.PLUSP, "real")
535    {
536      @Override
537      public LispObject execute(LispObject arg) throws ConditionThrowable
538      {
539        return arg.PLUSP();
540      }
541    };
542
543  // ### minusp
544  private static final Primitive MINUSP =
545    new Primitive(Symbol.MINUSP, "real")
546    {
547      @Override
548      public LispObject execute(LispObject arg) throws ConditionThrowable
549      {
550        return arg.MINUSP();
551      }
552    };
553
554  // ### zerop
555  private static final Primitive ZEROP =
556    new Primitive(Symbol.ZEROP, "number")
557    {
558      @Override
559      public LispObject execute(LispObject arg) throws ConditionThrowable
560      {
561        return arg.ZEROP();
562      }
563    };
564
565  // ### fixnump
566  private static final Primitive FIXNUMP =
567    new Primitive("fixnump", PACKAGE_EXT, true)
568    {
569      @Override
570      public LispObject execute(LispObject arg) throws ConditionThrowable
571      {
572        return arg instanceof Fixnum ? T : NIL;
573      }
574    };
575
576  // ### symbol-value
577  private static final Primitive SYMBOL_VALUE =
578    new Primitive(Symbol.SYMBOL_VALUE, "symbol")
579    {
580      @Override
581      public LispObject execute(LispObject arg) throws ConditionThrowable
582      {
583        final LispObject value;
584        value = checkSymbol(arg).symbolValue();
585        if (value instanceof SymbolMacro)
586          return error(new LispError(arg.writeToString() +
587                                      " has no dynamic value."));
588        return value;
589      }
590    };
591
592  // ### set symbol value => value
593  private static final Primitive SET =
594    new Primitive(Symbol.SET, "symbol value")
595    {
596      @Override
597      public LispObject execute(LispObject first, LispObject second)
598        throws ConditionThrowable
599      {
600            return LispThread.currentThread().setSpecialVariable(checkSymbol(first),
601                                                                 second);
602      }
603    };
604
605  // ### rplaca
606  private static final Primitive RPLACA =
607    new Primitive(Symbol.RPLACA, "cons object")
608    {
609      @Override
610      public LispObject execute(LispObject first, LispObject second)
611        throws ConditionThrowable
612      {
613        first.setCar(second);
614        return first;
615      }
616    };
617
618  // ### rplacd
619  private static final Primitive RPLACD =
620    new Primitive(Symbol.RPLACD, "cons object")
621    {
622      @Override
623      public LispObject execute(LispObject first, LispObject second)
624        throws ConditionThrowable
625      {
626        first.setCdr(second);
627        return first;
628      }
629    };
630
631  // ### +
632  private static final Primitive ADD =
633    new Primitive(Symbol.PLUS, "&rest numbers")
634    {
635      @Override
636      public LispObject execute()
637      {
638        return Fixnum.ZERO;
639      }
640      @Override
641      public LispObject execute(LispObject arg) throws ConditionThrowable
642      {
643        if (arg.numberp())
644          return arg;
645        return type_error(arg, Symbol.NUMBER);
646      }
647      @Override
648      public LispObject execute(LispObject first, LispObject second)
649        throws ConditionThrowable
650      {
651        return first.add(second);
652      }
653      @Override
654      public LispObject execute(LispObject first, LispObject second,
655                                LispObject third)
656        throws ConditionThrowable
657      {
658        return first.add(second).add(third);
659      }
660      @Override
661      public LispObject execute(LispObject[] args) throws ConditionThrowable
662      {
663        LispObject result = Fixnum.ZERO;
664        final int length = args.length;
665        for (int i = 0; i < length; i++)
666          result = result.add(args[i]);
667        return result;
668      }
669    };
670
671  // ### 1+
672  private static final Primitive ONE_PLUS =
673    new Primitive(Symbol.ONE_PLUS, "number")
674    {
675      @Override
676      public LispObject execute(LispObject arg) throws ConditionThrowable
677      {
678        return arg.incr();
679      }
680    };
681
682  // ### -
683  private static final Primitive SUBTRACT =
684    new Primitive(Symbol.MINUS, "minuend &rest subtrahends")
685    {
686      @Override
687      public LispObject execute() throws ConditionThrowable
688      {
689        return error(new WrongNumberOfArgumentsException(this));
690      }
691      @Override
692      public LispObject execute(LispObject arg) throws ConditionThrowable
693      {
694        return arg.negate();
695      }
696      @Override
697      public LispObject execute(LispObject first, LispObject second)
698        throws ConditionThrowable
699      {
700        return first.subtract(second);
701      }
702      @Override
703      public LispObject execute(LispObject[] args) throws ConditionThrowable
704      {
705        LispObject result = args[0];
706        for (int i = 1; i < args.length; i++)
707          result = result.subtract(args[i]);
708        return result;
709      }
710    };
711
712  // ### 1-
713  private static final Primitive ONE_MINUS =
714    new Primitive(Symbol.ONE_MINUS, "number")
715    {
716      @Override
717      public LispObject execute(LispObject arg) throws ConditionThrowable
718      {
719        return arg.decr();
720      }
721    };
722
723  // ### when
724  private static final SpecialOperator WHEN =
725    new SpecialOperator(Symbol.WHEN)
726    {
727      @Override
728      public LispObject execute(LispObject args, Environment env)
729        throws ConditionThrowable
730      {
731        if (args == NIL)
732          return error(new WrongNumberOfArgumentsException(this));
733        final LispThread thread = LispThread.currentThread();
734        if (eval(args.car(), env, thread) != NIL)
735          {
736            args = args.cdr();
737            thread.clearValues();
738            return progn(args, env, thread);
739          }
740        return thread.setValues(NIL);
741      }
742    };
743
744  // ### unless
745  private static final SpecialOperator UNLESS =
746    new SpecialOperator(Symbol.UNLESS)
747    {
748      @Override
749      public LispObject execute(LispObject args, Environment env)
750        throws ConditionThrowable
751      {
752        if (args == NIL)
753          return error(new WrongNumberOfArgumentsException(this));
754        final LispThread thread = LispThread.currentThread();
755        if (eval(args.car(), env, thread) == NIL)
756          {
757            args = args.cdr();
758            thread.clearValues();
759            return progn(args, env, thread);
760          }
761        return thread.setValues(NIL);
762      }
763    };
764
765  // ### %stream-output-object object stream => object
766  private static final Primitive _STREAM_OUTPUT_OBJECT =
767    new Primitive("%stream-output-object", PACKAGE_SYS, true)
768    {
769      @Override
770      public LispObject execute(LispObject first, LispObject second)
771        throws ConditionThrowable
772      {
773            checkStream(second)._writeString(first.writeToString());
774            return first;
775      }
776    };
777
778  // ### %output-object object stream => object
779  private static final Primitive _OUTPUT_OBJECT =
780    new Primitive("%output-object", PACKAGE_SYS, true)
781    {
782      @Override
783      public LispObject execute(LispObject first, LispObject second)
784        throws ConditionThrowable
785      {
786        final LispObject out;
787            if (second == T)
788              out = Symbol.TERMINAL_IO.symbolValue();
789            else if (second == NIL)
790              out = Symbol.STANDARD_OUTPUT.symbolValue();
791            else
792              out = second;
793        checkStream(out)._writeString(first.writeToString());
794        return first;
795      }
796    };
797
798  // ### %write-to-string object => string
799  private static final Primitive _WRITE_TO_STRING =
800    new Primitive("%write-to-string", PACKAGE_SYS, false)
801    {
802      @Override
803      public LispObject execute(LispObject arg) throws ConditionThrowable
804      {
805        return new SimpleString(arg.writeToString());
806      }
807    };
808
809  // ### %stream-terpri output-stream => nil
810  private static final Primitive _STREAM_TERPRI =
811    new Primitive("%stream-terpri", PACKAGE_SYS, true, "output-stream")
812    {
813      @Override
814      public LispObject execute(LispObject arg) throws ConditionThrowable
815      {
816            checkStream(arg)._writeChar('\n');
817            return NIL;
818      }
819    };
820
821  // ### %terpri output-stream => nil
822  private static final Primitive _TERPRI =
823    new Primitive("%terpri", PACKAGE_SYS, false, "output-stream")
824    {
825      @Override
826      public LispObject execute(LispObject arg) throws ConditionThrowable
827      {
828        if (arg == T)
829          arg = Symbol.TERMINAL_IO.symbolValue();
830        else if (arg == NIL)
831          arg = Symbol.STANDARD_OUTPUT.symbolValue();
832        final Stream stream;
833        stream = checkStream(arg);
834        return stream.terpri();
835      }
836    };
837
838  // ### %fresh-line
839  // %fresh-line &optional output-stream => generalized-boolean
840  private static final Primitive _FRESH_LINE =
841    new Primitive("%fresh-line", PACKAGE_SYS, false, "output-stream")
842    {
843      @Override
844      public LispObject execute(LispObject arg) throws ConditionThrowable
845      {
846        if (arg == T)
847          arg = Symbol.TERMINAL_IO.symbolValue();
848        else if (arg == NIL)
849          arg = Symbol.STANDARD_OUTPUT.symbolValue();
850        final Stream stream;
851        stream = checkStream(arg);
852        return stream.freshLine();
853      }
854    };
855
856  // ### boundp
857  // Determines only whether a symbol has a value in the global environment;
858  // any lexical bindings are ignored.
859  private static final Primitive BOUNDP =
860    new Primitive(Symbol.BOUNDP, "symbol")
861    {
862      @Override
863      public LispObject execute(LispObject arg) throws ConditionThrowable
864      {
865        final Symbol symbol;
866        symbol = checkSymbol(arg);
867        // PROGV: "If too few values are supplied, the remaining symbols
868        // are bound and then made to have no value." So BOUNDP must
869        // explicitly check for a binding with no value.
870        SpecialBinding binding =
871          LispThread.currentThread().getSpecialBinding(symbol);
872        if (binding != null)
873          return binding.value != null ? T : NIL;
874        // No binding.
875        return symbol.getSymbolValue() != null ? T : NIL;
876      }
877    };
878
879  // ### fboundp
880  private static final Primitive FBOUNDP =
881    new Primitive(Symbol.FBOUNDP, "name")
882    {
883      @Override
884      public LispObject execute(LispObject arg) throws ConditionThrowable
885      {
886        if (arg instanceof Symbol)
887          return arg.getSymbolFunction() != null ? T : NIL;
888        if (isValidSetfFunctionName(arg))
889          {
890            LispObject f = get(arg.cadr(), Symbol.SETF_FUNCTION, null);
891            return f != null ? T : NIL;
892          }
893        return type_error(arg, FUNCTION_NAME);
894      }
895    };
896
897  // ### fmakunbound name => name
898  private static final Primitive FMAKUNBOUND =
899    new Primitive(Symbol.FMAKUNBOUND, "name")
900    {
901      @Override
902      public LispObject execute(LispObject arg) throws ConditionThrowable
903      {
904        if (arg instanceof Symbol)
905          {
906            checkSymbol(arg).setSymbolFunction(null);
907            return arg;
908          }
909        if (isValidSetfFunctionName(arg))
910          {
911            remprop((Symbol)arg.cadr(), Symbol.SETF_FUNCTION);
912            return arg;
913          }
914        return type_error(arg, FUNCTION_NAME);
915      }
916    };
917
918  // ### setf-function-name-p
919  private static final Primitive SETF_FUNCTION_NAME_P =
920    new Primitive("setf-function-name-p", PACKAGE_SYS, true, "thing")
921    {
922      @Override
923      public LispObject execute(LispObject arg) throws ConditionThrowable
924      {
925        return isValidSetfFunctionName(arg) ? T : NIL;
926      }
927    };
928
929  // ### remprop
930  private static final Primitive REMPROP =
931    new Primitive(Symbol.REMPROP, "symbol indicator")
932    {
933      @Override
934      public LispObject execute(LispObject first, LispObject second)
935        throws ConditionThrowable
936      {
937        return remprop(checkSymbol(first), second);
938      }
939    };
940
941  // ### append
942  public static final Primitive APPEND =
943    new Primitive(Symbol.APPEND, "&rest lists")
944    {
945      @Override
946      public LispObject execute()
947      {
948        return NIL;
949      }
950      @Override
951      public LispObject execute(LispObject arg)
952      {
953        return arg;
954      }
955      @Override
956      public LispObject execute(LispObject first, LispObject second)
957        throws ConditionThrowable
958      {
959        if (first == NIL)
960          return second;
961        // APPEND is required to copy its first argument.
962        Cons result = new Cons(first.car());
963        Cons splice = result;
964        first = first.cdr();
965        while (first != NIL)
966          {
967            Cons temp = new Cons(first.car());
968            splice.cdr = temp;
969            splice = temp;
970            first = first.cdr();
971          }
972        splice.cdr = second;
973        return result;
974      }
975      @Override
976      public LispObject execute(LispObject first, LispObject second,
977                                LispObject third)
978        throws ConditionThrowable
979      {
980        if (first == NIL)
981          return execute(second, third);
982        Cons result = new Cons(first.car());
983        Cons splice = result;
984        first = first.cdr();
985        while (first != NIL)
986          {
987            Cons temp = new Cons(first.car());
988            splice.cdr = temp;
989            splice = temp;
990            first = first.cdr();
991          }
992        while (second != NIL)
993          {
994            Cons temp = new Cons(second.car());
995            splice.cdr = temp;
996            splice = temp;
997            second = second.cdr();
998          }
999        splice.cdr = third;
1000        return result;
1001      }
1002      @Override
1003      public LispObject execute(LispObject[] args) throws ConditionThrowable
1004      {
1005        Cons result = null;
1006        Cons splice = null;
1007        final int limit = args.length - 1;
1008        int i;
1009        for (i = 0; i < limit; i++)
1010          {
1011            LispObject top = args[i];
1012            if (top == NIL)
1013              continue;
1014            result = new Cons(top.car());
1015            splice = result;
1016            top = top.cdr();
1017            while (top != NIL)
1018              {
1019                Cons temp = new Cons(top.car());
1020                splice.cdr = temp;
1021                splice = temp;
1022                top = top.cdr();
1023              }
1024            break;
1025          }
1026        if (result == null)
1027          return args[i];
1028        for (++i; i < limit; i++)
1029          {
1030            LispObject top = args[i];
1031            while (top != NIL)
1032              {
1033                Cons temp = new Cons(top.car());
1034                splice.cdr = temp;
1035                splice = temp;
1036                top = top.cdr();
1037              }
1038          }
1039        splice.cdr = args[i];
1040        return result;
1041      }
1042    };
1043
1044  // ### nconc
1045  private static final Primitive NCONC =
1046    new Primitive(Symbol.NCONC, "&rest lists")
1047    {
1048      @Override
1049      public LispObject execute()
1050      {
1051        return NIL;
1052      }
1053      @Override
1054      public LispObject execute(LispObject arg)
1055      {
1056        return arg;
1057      }
1058      @Override
1059      public LispObject execute(LispObject first, LispObject second)
1060        throws ConditionThrowable
1061      {
1062        if (first == NIL)
1063          return second;
1064        if (first instanceof Cons)
1065          {
1066            LispObject result = first;
1067            Cons splice = null;
1068            while (first instanceof Cons)
1069              {
1070                splice = (Cons) first;
1071                first = splice.cdr;
1072              }
1073            splice.cdr = second;
1074            return result;
1075          }
1076        return type_error(first, Symbol.LIST);
1077      }
1078      @Override
1079      public LispObject execute(LispObject[] array) throws ConditionThrowable
1080      {
1081        LispObject result = null;
1082        Cons splice = null;
1083        final int limit = array.length - 1;
1084        int i;
1085        for (i = 0; i < limit; i++)
1086          {
1087            LispObject list = array[i];
1088            if (list == NIL)
1089              continue;
1090            if (list instanceof Cons)
1091              {
1092                if (splice != null)
1093                  {
1094                    splice.cdr = list;
1095                    splice = (Cons) list;
1096                  }
1097                while (list instanceof Cons)
1098                  {
1099                    if (result == null)
1100                      {
1101                        result = list;
1102                        splice = (Cons) result;
1103                      }
1104                    else
1105                      splice = (Cons) list;
1106                    list = splice.cdr;
1107                  }
1108              }
1109            else
1110              type_error(list, Symbol.LIST);
1111          }
1112        if (result == null)
1113          return array[i];
1114        splice.cdr = array[i];
1115        return result;
1116      }
1117    };
1118
1119  // ### =
1120  // Numeric equality.
1121  private static final Primitive EQUALS =
1122    new Primitive(Symbol.EQUALS, "&rest numbers")
1123    {
1124      @Override
1125      public LispObject execute() throws ConditionThrowable
1126      {
1127        return error(new WrongNumberOfArgumentsException(this));
1128      }
1129      @Override
1130      public LispObject execute(LispObject arg)
1131      {
1132        return T;
1133      }
1134      @Override
1135      public LispObject execute(LispObject first, LispObject second)
1136        throws ConditionThrowable
1137      {
1138        return first.isEqualTo(second) ? T : NIL;
1139      }
1140      @Override
1141      public LispObject execute(LispObject first, LispObject second,
1142                                LispObject third)
1143        throws ConditionThrowable
1144      {
1145        if (first.isEqualTo(second) && second.isEqualTo(third))
1146          return T;
1147        else
1148          return NIL;
1149      }
1150      @Override
1151      public LispObject execute(LispObject[] array) throws ConditionThrowable
1152      {
1153        final int length = array.length;
1154        final LispObject obj = array[0];
1155        for (int i = 1; i < length; i++)
1156          {
1157            if (array[i].isNotEqualTo(obj))
1158              return NIL;
1159          }
1160        return T;
1161      }
1162    };
1163
1164  // ### /=
1165  // Returns true if no two numbers are the same; otherwise returns false.
1166  private static final Primitive NOT_EQUALS =
1167    new Primitive(Symbol.NOT_EQUALS, "&rest numbers")
1168    {
1169      @Override
1170      public LispObject execute() throws ConditionThrowable
1171      {
1172        return error(new WrongNumberOfArgumentsException(this));
1173      }
1174      @Override
1175      public LispObject execute(LispObject arg)
1176      {
1177        return T;
1178      }
1179      @Override
1180      public LispObject execute(LispObject first, LispObject second)
1181        throws ConditionThrowable
1182      {
1183        return first.isNotEqualTo(second) ? T : NIL;
1184      }
1185      @Override
1186      public LispObject execute(LispObject first, LispObject second,
1187                                LispObject third)
1188        throws ConditionThrowable
1189      {
1190        if (first.isEqualTo(second))
1191          return NIL;
1192        if (first.isEqualTo(third))
1193          return NIL;
1194        if (second.isEqualTo(third))
1195          return NIL;
1196        return T;
1197      }
1198      @Override
1199      public LispObject execute(LispObject[] array) throws ConditionThrowable
1200      {
1201        final int length = array.length;
1202        for (int i = 0; i < length; i++)
1203          {
1204            final LispObject obj = array[i];
1205            for (int j = i+1; j < length; j++)
1206              {
1207                if (array[j].isEqualTo(obj))
1208                  return NIL;
1209              }
1210          }
1211        return T;
1212      }
1213    };
1214
1215  // ### <
1216  // Numeric comparison.
1217  private static final Primitive LT =
1218    new Primitive(Symbol.LT, "&rest numbers")
1219    {
1220      @Override
1221      public LispObject execute() throws ConditionThrowable
1222      {
1223        return error(new WrongNumberOfArgumentsException(this));
1224      }
1225      @Override
1226      public LispObject execute(LispObject arg)
1227      {
1228        return T;
1229      }
1230      @Override
1231      public LispObject execute(LispObject first, LispObject second)
1232        throws ConditionThrowable
1233      {
1234        return first.isLessThan(second) ? T : NIL;
1235      }
1236      @Override
1237      public LispObject execute(LispObject first, LispObject second,
1238                                LispObject third)
1239        throws ConditionThrowable
1240      {
1241        if (first.isLessThan(second) && second.isLessThan(third))
1242          return T;
1243        else
1244          return NIL;
1245      }
1246      @Override
1247      public LispObject execute(LispObject[] array) throws ConditionThrowable
1248      {
1249        final int length = array.length;
1250        for (int i = 1; i < length; i++)
1251          {
1252            if (array[i].isLessThanOrEqualTo(array[i-1]))
1253              return NIL;
1254          }
1255        return T;
1256      }
1257    };
1258
1259  // ### <=
1260  private static final Primitive LE =
1261    new Primitive(Symbol.LE, "&rest numbers")
1262    {
1263      @Override
1264      public LispObject execute() throws ConditionThrowable
1265      {
1266        return error(new WrongNumberOfArgumentsException(this));
1267      }
1268      @Override
1269      public LispObject execute(LispObject arg)
1270      {
1271        return T;
1272      }
1273      @Override
1274      public LispObject execute(LispObject first, LispObject second)
1275        throws ConditionThrowable
1276      {
1277        return first.isLessThanOrEqualTo(second) ? T : NIL;
1278      }
1279      @Override
1280      public LispObject execute(LispObject first, LispObject second,
1281                                LispObject third)
1282        throws ConditionThrowable
1283      {
1284        if (first.isLessThanOrEqualTo(second) && second.isLessThanOrEqualTo(third))
1285          return T;
1286        else
1287          return NIL;
1288      }
1289      @Override
1290      public LispObject execute(LispObject[] array) throws ConditionThrowable
1291      {
1292        final int length = array.length;
1293        for (int i = 1; i < length; i++)
1294          {
1295            if (array[i].isLessThan(array[i-1]))
1296              return NIL;
1297          }
1298        return T;
1299      }
1300    };
1301
1302  // ### >
1303  private static final Primitive GT =
1304    new Primitive(Symbol.GT, "&rest numbers")
1305    {
1306      @Override
1307      public LispObject execute() throws ConditionThrowable
1308      {
1309        return error(new WrongNumberOfArgumentsException(this));
1310      }
1311      @Override
1312      public LispObject execute(LispObject arg)
1313      {
1314        return T;
1315      }
1316      @Override
1317      public LispObject execute(LispObject first, LispObject second)
1318        throws ConditionThrowable
1319      {
1320        return first.isGreaterThan(second) ? T : NIL;
1321      }
1322      @Override
1323      public LispObject execute(LispObject first, LispObject second,
1324                                LispObject third)
1325        throws ConditionThrowable
1326      {
1327        if (first.isGreaterThan(second) && second.isGreaterThan(third))
1328          return T;
1329        else
1330          return NIL;
1331      }
1332      @Override
1333      public LispObject execute(LispObject[] array) throws ConditionThrowable
1334      {
1335        final int length = array.length;
1336        for (int i = 1; i < length; i++)
1337          {
1338            if (array[i].isGreaterThanOrEqualTo(array[i-1]))
1339              return NIL;
1340          }
1341        return T;
1342      }
1343    };
1344
1345  // ### >=
1346  private static final Primitive GE =
1347    new Primitive(Symbol.GE, "&rest numbers")
1348    {
1349      @Override
1350      public LispObject execute() throws ConditionThrowable
1351      {
1352        return error(new WrongNumberOfArgumentsException(this));
1353      }
1354      @Override
1355      public LispObject execute(LispObject arg)
1356      {
1357        return T;
1358      }
1359      @Override
1360      public LispObject execute(LispObject first, LispObject second)
1361        throws ConditionThrowable
1362      {
1363        return first.isGreaterThanOrEqualTo(second) ? T : NIL;
1364      }
1365      @Override
1366      public LispObject execute(LispObject first, LispObject second,
1367                                LispObject third)
1368        throws ConditionThrowable
1369      {
1370        if (first.isGreaterThanOrEqualTo(second) && second.isGreaterThanOrEqualTo(third))
1371          return T;
1372        else
1373          return NIL;
1374      }
1375      @Override
1376      public LispObject execute(LispObject[] array) throws ConditionThrowable
1377      {
1378        final int length = array.length;
1379        for (int i = 1; i < length; i++)
1380          {
1381            if (array[i].isGreaterThan(array[i-1]))
1382              return NIL;
1383          }
1384        return T;
1385      }
1386    };
1387
1388  // ### nth n list => object
1389  private static final Primitive NTH = new Primitive(Symbol.NTH, "n list")
1390    {
1391      @Override
1392      public LispObject execute(LispObject first, LispObject second)
1393        throws ConditionThrowable
1394      {
1395        return second.NTH(first);
1396      }
1397    };
1398
1399  // ### %set-nth n list new-object => new-object
1400  private static final Primitive _SET_NTH =
1401    new Primitive("%set-nth", PACKAGE_SYS, false)
1402    {
1403      @Override
1404      public LispObject execute(LispObject first, LispObject second,
1405                                LispObject third)
1406        throws ConditionThrowable
1407      {
1408        int index = Fixnum.getValue(first);
1409        if (index < 0)
1410          error(new TypeError("(SETF NTH): invalid index " + index + "."));
1411        int i = 0;
1412        while (true)
1413          {
1414            if (i == index)
1415              {
1416                second.setCar(third);
1417                return third;
1418              }
1419            second = second.cdr();
1420            if (second == NIL)
1421              {
1422                return error(new LispError("(SETF NTH): the index " +
1423                                            index + "is too large."));
1424              }
1425            ++i;
1426          }
1427      }
1428    };
1429
1430  // ### nthcdr
1431  private static final Primitive NTHCDR =
1432    new Primitive(Symbol.NTHCDR, "n list")
1433    {
1434      @Override
1435      public LispObject execute(LispObject first, LispObject second)
1436        throws ConditionThrowable
1437      {
1438        final int index = Fixnum.getValue(first);
1439        if (index < 0)
1440          return type_error(first,
1441                                 list(Symbol.INTEGER, Fixnum.ZERO));
1442        for (int i = 0; i < index; i++)
1443          {
1444            second = second.cdr();
1445            if (second == NIL)
1446              return NIL;
1447          }
1448        return second;
1449      }
1450    };
1451
1452  // ### error
1453  private static final Primitive ERROR =
1454    new Primitive(Symbol.ERROR, "datum &rest arguments")
1455    {
1456      @Override
1457      public LispObject execute(LispObject[] args) throws ConditionThrowable
1458      {
1459        Error e = new Error();
1460
1461        e.printStackTrace();
1462
1463        System.out.println("ERROR placeholder called with arguments:");
1464        for (LispObject a : args)
1465            System.out.println(a.writeToString());
1466
1467        //###FIXME: Bail out, but do it nicer...
1468        System.exit(1);
1469        return NIL;
1470      }
1471    };
1472
1473  // ### signal
1474  private static final Primitive SIGNAL =
1475    new Primitive(Symbol.SIGNAL, "datum &rest arguments")
1476    {
1477      @Override
1478      public LispObject execute(LispObject[] args) throws ConditionThrowable
1479      {
1480        if (args.length < 1)
1481          throw new ConditionThrowable(new WrongNumberOfArgumentsException(this));
1482        if (args[0] instanceof Condition)
1483          throw new ConditionThrowable((Condition)args[0]);
1484        throw new ConditionThrowable(new SimpleCondition());
1485      }
1486    };
1487
1488  // ### undefined-function-called
1489  // Redefined in restart.lisp.
1490  private static final Primitive UNDEFINED_FUNCTION_CALLED =
1491    new Primitive(Symbol.UNDEFINED_FUNCTION_CALLED, "name arguments")
1492    {
1493      @Override
1494      public LispObject execute(LispObject first, LispObject second)
1495        throws ConditionThrowable
1496      {
1497        return error(new UndefinedFunction(first));
1498      }
1499    };
1500
1501  // ### %format
1502  private static final Primitive _FORMAT =
1503    new Primitive("%format", PACKAGE_SYS, false,
1504                  "destination control-string &rest args")
1505    {
1506      @Override
1507      public LispObject execute(LispObject first, LispObject second,
1508                                LispObject third)
1509        throws ConditionThrowable
1510      {
1511        LispObject destination = first;
1512        // Copy remaining arguments.
1513        LispObject[] _args = new LispObject[2];
1514        _args[0] = second;
1515        _args[1] = third;
1516        String s = _format(_args);
1517        return outputFormattedString(s, destination);
1518      }
1519      @Override
1520      public LispObject execute(LispObject first, LispObject second,
1521                                LispObject third, LispObject fourth)
1522        throws ConditionThrowable
1523      {
1524        LispObject destination = first;
1525        // Copy remaining arguments.
1526        LispObject[] _args = new LispObject[3];
1527        _args[0] = second;
1528        _args[1] = third;
1529        _args[2] = fourth;
1530        String s = _format(_args);
1531        return outputFormattedString(s, destination);
1532      }
1533      @Override
1534      public LispObject execute(LispObject[] args) throws ConditionThrowable
1535      {
1536        if (args.length < 2)
1537          return error(new WrongNumberOfArgumentsException(this));
1538        LispObject destination = args[0];
1539        // Copy remaining arguments.
1540        LispObject[] _args = new LispObject[args.length - 1];
1541        for (int i = 0; i < _args.length; i++)
1542          _args[i] = args[i+1];
1543        String s = _format(_args);
1544        return outputFormattedString(s, destination);
1545      }
1546      private final String _format(LispObject[] args)
1547        throws ConditionThrowable
1548      {
1549        LispObject formatControl = args[0];
1550        LispObject formatArguments = NIL;
1551        for (int i = 1; i < args.length; i++)
1552          formatArguments = new Cons(args[i], formatArguments);
1553        formatArguments = formatArguments.nreverse();
1554        return format(formatControl, formatArguments);
1555      }
1556      private final LispObject outputFormattedString(String s,
1557                                                     LispObject destination)
1558        throws ConditionThrowable
1559      {
1560        if (destination == T)
1561          {
1562            checkCharacterOutputStream(Symbol.STANDARD_OUTPUT.symbolValue())._writeString(s);
1563            return NIL;
1564          }
1565        if (destination == NIL)
1566          return new SimpleString(s);
1567        if (destination instanceof TwoWayStream)
1568          {
1569            Stream out = ((TwoWayStream)destination).getOutputStream();
1570            if (out instanceof Stream)
1571              {
1572                (out)._writeString(s);
1573                return NIL;
1574              }
1575            error(new TypeError("The value " +
1576                                 destination.writeToString() +
1577                                 " is not a character output stream."));
1578          }
1579        if (destination instanceof Stream)
1580          {
1581            ((Stream)destination)._writeString(s);
1582            return NIL;
1583          }
1584        return NIL;
1585      }
1586    };
1587
1588  private static final Symbol _SIMPLE_FORMAT_FUNCTION_ =
1589    internSpecial("*SIMPLE-FORMAT-FUNCTION*", PACKAGE_SYS, _FORMAT);
1590
1591  private static void checkRedefinition(LispObject arg)
1592    throws ConditionThrowable
1593  {
1594    final LispThread thread = LispThread.currentThread();
1595    if (_WARN_ON_REDEFINITION_.symbolValue(thread) != NIL)
1596      {
1597        if (arg instanceof Symbol)
1598          {
1599            LispObject oldDefinition = arg.getSymbolFunction();
1600            if (oldDefinition != null && !(oldDefinition instanceof Autoload))
1601              {
1602                LispObject oldSource =
1603                  Extensions.SOURCE_PATHNAME.execute(arg);
1604                LispObject currentSource = _SOURCE_.symbolValue(thread);
1605                if (currentSource == NIL)
1606                  currentSource = Keyword.TOP_LEVEL;
1607                if (oldSource != NIL)
1608                  {
1609                    if (currentSource.equal(oldSource))
1610                      return; // OK
1611                  }
1612                if (currentSource == Keyword.TOP_LEVEL)
1613                  {
1614                    Symbol.STYLE_WARN.execute(new SimpleString("redefining ~S at top level"),
1615                                              arg);
1616
1617                  }
1618                else
1619                  {
1620                    SpecialBinding lastSpecialBinding = thread.lastSpecialBinding;
1621                    thread.bindSpecial(Symbol._PACKAGE_, PACKAGE_CL);
1622                    try
1623                      {
1624                        Symbol.STYLE_WARN.execute(new SimpleString("redefining ~S in ~S"),
1625                                                  arg, currentSource);
1626                      }
1627                    finally
1628                      {
1629                        thread.lastSpecialBinding = lastSpecialBinding;
1630                      }
1631                  }
1632              }
1633          }
1634      }
1635  }
1636
1637  // ### %defun name definition => name
1638  private static final Primitive _DEFUN =
1639    new Primitive("%defun", PACKAGE_SYS, true, "name definition")
1640    {
1641      @Override
1642      public LispObject execute(LispObject name, LispObject definition)
1643        throws ConditionThrowable
1644      {
1645        if (name instanceof Symbol)
1646          {
1647            Symbol symbol = (Symbol) name;
1648            if (symbol.getSymbolFunction() instanceof SpecialOperator)
1649              {
1650                String message =
1651                  symbol.getName() + " is a special operator and may not be redefined.";
1652                return error(new ProgramError(message));
1653              }
1654          }
1655        else if (!isValidSetfFunctionName(name))
1656          return type_error(name, FUNCTION_NAME);
1657        if (definition instanceof Function)
1658          {
1659            Symbol.FSET.execute(name, definition, NIL,
1660                                ((Function)definition).getLambdaList());
1661            return name;
1662          }
1663        return type_error(definition, Symbol.FUNCTION);
1664      }
1665    };
1666
1667  // ### fdefinition-block-name
1668  private static final Primitive FDEFINITION_BLOCK_NAME =
1669    new Primitive("fdefinition-block-name", PACKAGE_SYS, true, "function-name")
1670    {
1671      @Override
1672      public LispObject execute(LispObject arg) throws ConditionThrowable
1673      {
1674        if (arg instanceof Symbol)
1675          return arg;
1676        if (isValidSetfFunctionName(arg))
1677          return arg.cadr();
1678        return type_error(arg, FUNCTION_NAME);
1679      }
1680    };
1681
1682  // ### macro-function
1683  private static final Primitive MACRO_FUNCTION =
1684    new Primitive(Symbol.MACRO_FUNCTION, "symbol &optional environment")
1685    {
1686      @Override
1687      public LispObject execute(LispObject arg) throws ConditionThrowable
1688      {
1689        LispObject obj = arg.getSymbolFunction();
1690        if (obj instanceof AutoloadMacro)
1691          {
1692            ((AutoloadMacro)obj).load();
1693            obj = arg.getSymbolFunction();
1694          }
1695        if (obj instanceof MacroObject)
1696          return ((MacroObject)obj).expander;
1697        if (obj instanceof SpecialOperator)
1698          {
1699            obj = get(arg, Symbol.MACROEXPAND_MACRO, NIL);
1700            if (obj instanceof AutoloadMacro)
1701              {
1702                ((AutoloadMacro)obj).load();
1703                obj = get(arg, Symbol.MACROEXPAND_MACRO, NIL);
1704              }
1705            if (obj instanceof MacroObject)
1706              return ((MacroObject)obj).expander;
1707          }
1708        return NIL;
1709      }
1710      @Override
1711      public LispObject execute(LispObject first, LispObject second)
1712        throws ConditionThrowable
1713      {
1714        LispObject obj;
1715        if (second != NIL)
1716          {
1717            Environment env = checkEnvironment(second);
1718            obj = env.lookupFunction(first);
1719          }
1720        else
1721          obj = first.getSymbolFunction();
1722        if (obj instanceof AutoloadMacro)
1723          {
1724            ((AutoloadMacro)obj).load();
1725            obj = first.getSymbolFunction();
1726          }
1727        if (obj instanceof MacroObject)
1728          return ((MacroObject)obj).expander;
1729        if (obj instanceof SpecialOperator)
1730          {
1731            obj = get(first, Symbol.MACROEXPAND_MACRO, NIL);
1732            if (obj instanceof AutoloadMacro)
1733              {
1734                ((AutoloadMacro)obj).load();
1735                obj = get(first, Symbol.MACROEXPAND_MACRO, NIL);
1736              }
1737            if (obj instanceof MacroObject)
1738              return ((MacroObject)obj).expander;
1739          }
1740        return NIL;
1741      }
1742    };
1743
1744  // ### defmacro
1745  private static final SpecialOperator DEFMACRO =
1746    new SpecialOperator(Symbol.DEFMACRO)
1747    {
1748      @Override
1749      public LispObject execute(LispObject args, Environment env)
1750        throws ConditionThrowable
1751      {
1752        Symbol symbol = checkSymbol(args.car());
1753        LispObject lambdaList = checkList(args.cadr());
1754        LispObject body = args.cddr();
1755        LispObject block = new Cons(Symbol.BLOCK, new Cons(symbol, body));
1756        LispObject toBeApplied =
1757          list(Symbol.FUNCTION, list(Symbol.LAMBDA, lambdaList, block));
1758        final LispThread thread = LispThread.currentThread();
1759        LispObject formArg = gensym("FORM-", thread);
1760        LispObject envArg = gensym("ENV-", thread); // Ignored.
1761        LispObject expander =
1762          list(Symbol.LAMBDA, list(formArg, envArg),
1763                list(Symbol.APPLY, toBeApplied,
1764                      list(Symbol.CDR, formArg)));
1765        Closure expansionFunction = new Closure(expander, env);
1766        MacroObject macroObject =
1767          new MacroObject(symbol, expansionFunction);
1768        if (symbol.getSymbolFunction() instanceof SpecialOperator)
1769          put(symbol, Symbol.MACROEXPAND_MACRO, macroObject);
1770        else
1771          symbol.setSymbolFunction(macroObject);
1772        macroObject.setLambdaList(lambdaList);
1773        thread._values = null;
1774        return symbol;
1775      }
1776    };
1777
1778  // ### make-macro
1779  private static final Primitive MAKE_MACRO =
1780    new Primitive("make-macro", PACKAGE_SYS, true, "name expansion-function")
1781    {
1782      @Override
1783      public LispObject execute(LispObject first, LispObject second)
1784        throws ConditionThrowable
1785      {
1786        return new MacroObject(first, second);
1787      }
1788    };
1789
1790  // ### macro-function-p
1791  private static final Primitive MACRO_FUNCTION_P =
1792      new Primitive("macro-function-p", PACKAGE_SYS, true, "value")
1793  {
1794      @Override
1795      public LispObject execute(LispObject arg) throws ConditionThrowable
1796      {
1797          return (arg instanceof MacroObject) ? T : NIL;
1798      }
1799  };
1800
1801
1802  // ### make-symbol-macro
1803  private static final Primitive MAKE_SYMBOL_MACRO =
1804      new Primitive("make-symbol-macro", PACKAGE_SYS, true, "expansion")
1805  {
1806      @Override
1807      public LispObject execute(LispObject arg) throws ConditionThrowable
1808      {
1809          return new SymbolMacro(arg);
1810      }
1811  };
1812
1813  // ### symbol-macro-p
1814  private static final Primitive SYMBOL_MACRO_P =
1815      new Primitive("symbol-macro-p", PACKAGE_SYS, true, "value")
1816  {
1817      @Override
1818      public LispObject execute(LispObject arg) throws ConditionThrowable
1819      {
1820          return (arg instanceof SymbolMacro) ? T : NIL;
1821      }
1822  };
1823
1824  // ### %defparameter
1825  private static final Primitive _DEFPARAMETER =
1826    new Primitive("%defparameter", PACKAGE_SYS, false)
1827    {
1828      @Override
1829      public LispObject execute(LispObject first, LispObject second,
1830                                LispObject third)
1831        throws ConditionThrowable
1832      {
1833        final Symbol symbol;
1834            symbol = checkSymbol(first);
1835        if (third instanceof AbstractString)
1836          symbol.setDocumentation(Symbol.VARIABLE, third);
1837        else if (third != NIL)
1838          type_error(third, Symbol.STRING);
1839        symbol.initializeSpecial(second);
1840        return symbol;
1841      }
1842    };
1843
1844  // ### %defvar
1845  private static final Primitive _DEFVAR =
1846    new Primitive("%defvar", PACKAGE_SYS, false)
1847    {
1848      @Override
1849      public LispObject execute(LispObject arg) throws ConditionThrowable
1850      {
1851        final Symbol symbol;
1852            symbol = checkSymbol(arg);
1853        symbol.setSpecial(true);
1854        return symbol;
1855      }
1856      @Override
1857      public LispObject execute(LispObject first, LispObject second)
1858        throws ConditionThrowable
1859      {
1860        final Symbol symbol;
1861            symbol = checkSymbol(first);
1862        symbol.initializeSpecial(second);
1863        return symbol;
1864      }
1865    };
1866
1867  // ### %defconstant name initial-value documentation => name
1868  private static final Primitive _DEFCONSTANT =
1869    new Primitive("%defconstant", PACKAGE_SYS, false)
1870    {
1871      @Override
1872      public LispObject execute(LispObject first, LispObject second,
1873                                LispObject third)
1874        throws ConditionThrowable
1875      {
1876        final Symbol symbol;
1877            symbol = checkSymbol(first);
1878        if (third != NIL)
1879          {
1880            if (third instanceof AbstractString)
1881              symbol.setDocumentation(Symbol.VARIABLE, third);
1882            else
1883              return type_error(third, Symbol.STRING);
1884          }
1885        symbol.initializeConstant(second);
1886        return symbol;
1887      }
1888    };
1889
1890  // ### cond
1891  private static final SpecialOperator COND =
1892    new SpecialOperator(Symbol.COND, "&rest clauses")
1893    {
1894      @Override
1895      public LispObject execute(LispObject args, Environment env)
1896        throws ConditionThrowable
1897      {
1898        final LispThread thread = LispThread.currentThread();
1899        LispObject result = NIL;
1900        while (args != NIL)
1901          {
1902            LispObject clause = args.car();
1903            result = eval(clause.car(), env, thread);
1904            thread._values = null;
1905            if (result != NIL)
1906              {
1907                LispObject body = clause.cdr();
1908                while (body != NIL)
1909                  {
1910                    result = eval(body.car(), env, thread);
1911                    body = ((Cons)body).cdr;
1912                  }
1913                return result;
1914              }
1915            args = ((Cons)args).cdr;
1916          }
1917        return result;
1918      }
1919    };
1920
1921  // ### case
1922  private static final SpecialOperator CASE =
1923    new SpecialOperator(Symbol.CASE, "keyform &body cases")
1924    {
1925      @Override
1926      public LispObject execute(LispObject args, Environment env)
1927        throws ConditionThrowable
1928      {
1929        final LispThread thread = LispThread.currentThread();
1930        LispObject key = eval(args.car(), env, thread);
1931        args = args.cdr();
1932        while (args != NIL)
1933          {
1934            LispObject clause = args.car();
1935            LispObject keys = clause.car();
1936            boolean match = false;
1937            if (keys.listp())
1938              {
1939                while (keys != NIL)
1940                  {
1941                    LispObject candidate = keys.car();
1942                    if (key.eql(candidate))
1943                      {
1944                        match = true;
1945                        break;
1946                      }
1947                    keys = keys.cdr();
1948                  }
1949              }
1950            else
1951              {
1952                LispObject candidate = keys;
1953                if (candidate == T || candidate == Symbol.OTHERWISE)
1954                  match = true;
1955                else if (key.eql(candidate))
1956                  match = true;
1957              }
1958            if (match)
1959              {
1960                return progn(clause.cdr(), env, thread);
1961              }
1962            args = args.cdr();
1963          }
1964        return NIL;
1965      }
1966    };
1967
1968  // ### ecase
1969  private static final SpecialOperator ECASE =
1970    new SpecialOperator(Symbol.ECASE, "keyform &body cases")
1971    {
1972      @Override
1973      public LispObject execute(LispObject args, Environment env)
1974        throws ConditionThrowable
1975      {
1976        final LispThread thread = LispThread.currentThread();
1977        LispObject key = eval(args.car(), env, thread);
1978        LispObject clauses = args.cdr();
1979        while (clauses != NIL)
1980          {
1981            LispObject clause = clauses.car();
1982            LispObject keys = clause.car();
1983            boolean match = false;
1984            if (keys.listp())
1985              {
1986                while (keys != NIL)
1987                  {
1988                    LispObject candidate = keys.car();
1989                    if (key.eql(candidate))
1990                      {
1991                        match = true;
1992                        break;
1993                      }
1994                    keys = keys.cdr();
1995                  }
1996              }
1997            else
1998              {
1999                LispObject candidate = keys;
2000                if (key.eql(candidate))
2001                  match = true;
2002              }
2003            if (match)
2004              {
2005                return progn(clause.cdr(), env, thread);
2006              }
2007            clauses = clauses.cdr();
2008          }
2009        LispObject expectedType = NIL;
2010        clauses = args.cdr();
2011        while (clauses != NIL)
2012          {
2013            LispObject clause = clauses.car();
2014            LispObject keys = clause.car();
2015            if (keys.listp())
2016              {
2017                while (keys != NIL)
2018                  {
2019                    expectedType = expectedType.push(keys.car());
2020                    keys = keys.cdr();
2021                  }
2022              }
2023            else
2024              expectedType = expectedType.push(keys);
2025            clauses = clauses.cdr();
2026          }
2027        expectedType = expectedType.nreverse();
2028        expectedType = expectedType.push(Symbol.MEMBER);
2029        return type_error(key, expectedType);
2030      }
2031    };
2032
2033  // ### upgraded-array-element-type typespec &optional environment
2034  // => upgraded-typespec
2035  private static final Primitive UPGRADED_ARRAY_ELEMENT_TYPE =
2036    new Primitive(Symbol.UPGRADED_ARRAY_ELEMENT_TYPE,
2037                  "typespec &optional environment")
2038    {
2039      @Override
2040      public LispObject execute(LispObject arg) throws ConditionThrowable
2041      {
2042        return getUpgradedArrayElementType(arg);
2043      }
2044      @Override
2045      public LispObject execute(LispObject first, LispObject second)
2046        throws ConditionThrowable
2047      {
2048        // Ignore environment.
2049        return getUpgradedArrayElementType(first);
2050      }
2051    };
2052
2053  // ### array-rank array => rank
2054  private static final Primitive ARRAY_RANK =
2055    new Primitive(Symbol.ARRAY_RANK, "array")
2056    {
2057      @Override
2058      public LispObject execute(LispObject arg) throws ConditionThrowable
2059      {
2060          return Fixnum.getInstance(checkArray(arg).getRank());
2061
2062      }
2063    };
2064
2065  // ### array-dimensions array => dimensions
2066  // Returns a list of integers. Fill pointer (if any) is ignored.
2067  private static final Primitive ARRAY_DIMENSIONS =
2068    new Primitive(Symbol.ARRAY_DIMENSIONS, "array")
2069    {
2070      @Override
2071      public LispObject execute(LispObject arg) throws ConditionThrowable
2072      {
2073            return checkArray(arg).getDimensions();
2074      }
2075    };
2076
2077  // ### array-dimension array axis-number => dimension
2078  private static final Primitive ARRAY_DIMENSION =
2079    new Primitive(Symbol.ARRAY_DIMENSION, "array axis-number")
2080    {
2081      @Override
2082      public LispObject execute(LispObject first, LispObject second)
2083        throws ConditionThrowable
2084      {
2085        final AbstractArray array = checkArray(first);
2086        return Fixnum.getInstance(array.getDimension(Fixnum.getValue(second)));
2087      }
2088    };
2089
2090  // ### array-total-size array => size
2091  private static final Primitive ARRAY_TOTAL_SIZE =
2092    new Primitive(Symbol.ARRAY_TOTAL_SIZE, "array")
2093    {
2094      @Override
2095      public LispObject execute(LispObject arg) throws ConditionThrowable
2096      {
2097          return Fixnum.getInstance(checkArray(arg).getTotalSize());
2098      }
2099    };
2100
2101
2102  // ### array-element-type
2103  // array-element-type array => typespec
2104  private static final Primitive ARRAY_ELEMENT_TYPE =
2105    new Primitive(Symbol.ARRAY_ELEMENT_TYPE, "array")
2106    {
2107      @Override
2108      public LispObject execute(LispObject arg) throws ConditionThrowable
2109      {
2110            return checkArray(arg).getElementType();
2111      }
2112    };
2113
2114  // ### adjustable-array-p
2115  private static final Primitive ADJUSTABLE_ARRAY_P =
2116    new Primitive(Symbol.ADJUSTABLE_ARRAY_P, "array")
2117    {
2118      @Override
2119      public LispObject execute(LispObject arg) throws ConditionThrowable
2120      {
2121            return checkArray(arg).isAdjustable() ? T : NIL;
2122      }
2123    };
2124
2125  // ### array-displacement array => displaced-to, displaced-index-offset
2126  private static final Primitive ARRAY_DISPLACEMENT =
2127    new Primitive(Symbol.ARRAY_DISPLACEMENT, "array")
2128    {
2129      @Override
2130      public LispObject execute(LispObject arg) throws ConditionThrowable
2131      {
2132            return checkArray(arg).arrayDisplacement();
2133
2134      }
2135    };
2136
2137  // ### array-in-bounds-p array &rest subscripts => generalized-boolean
2138  private static final Primitive ARRAY_IN_BOUNDS_P =
2139    new Primitive(Symbol.ARRAY_IN_BOUNDS_P, "array &rest subscripts")
2140    {
2141      @Override
2142      public LispObject execute(LispObject[] args) throws ConditionThrowable
2143      {
2144        if (args.length < 1)
2145          return error(new WrongNumberOfArgumentsException(this));
2146        final AbstractArray array;
2147                LispObject r = args[0];
2148            array = checkArray(r);
2149        int rank = array.getRank();
2150        if (rank != args.length - 1)
2151          {
2152            FastStringBuffer sb =
2153              new FastStringBuffer("ARRAY-IN-BOUNDS-P: ");
2154            sb.append("wrong number of subscripts (");
2155            sb.append(args.length - 1);
2156            sb.append(") for array of rank ");
2157            sb.append(rank);
2158            error(new ProgramError(sb.toString()));
2159          }
2160        for (int i = 0; i < rank; i++)
2161          {
2162            LispObject arg = args[i+1];
2163            if (arg instanceof Fixnum)
2164              {
2165                int subscript = ((Fixnum)arg).value;
2166                if (subscript < 0 || subscript >= array.getDimension(i))
2167                  return NIL;
2168              }
2169            else if (arg instanceof Bignum)
2170              return NIL;
2171            else
2172              type_error(arg, Symbol.INTEGER);
2173          }
2174        return T;
2175      }
2176    };
2177
2178  // ### %array-row-major-index array subscripts => index
2179  private static final Primitive _ARRAY_ROW_MAJOR_INDEX =
2180    new Primitive("%array-row-major-index", PACKAGE_SYS, false)
2181    {
2182      @Override
2183      public LispObject execute(LispObject first, LispObject second)
2184        throws ConditionThrowable
2185      {
2186        final AbstractArray array;
2187        array = checkArray(first);
2188        LispObject[] subscripts = second.copyToArray();
2189        return number(array.getRowMajorIndex(subscripts));
2190      }
2191    };
2192
2193  // ### aref array &rest subscripts => element
2194  private static final Primitive AREF =
2195    new Primitive(Symbol.AREF, "array &rest subscripts")
2196    {
2197      @Override
2198      public LispObject execute() throws ConditionThrowable
2199      {
2200        return error(new WrongNumberOfArgumentsException(this));
2201      }
2202      @Override
2203      public LispObject execute(LispObject arg) throws ConditionThrowable
2204      {
2205        final AbstractArray array;
2206        array = checkArray( arg);
2207        if (array.getRank() == 0)
2208          return array.AREF(0);
2209        FastStringBuffer sb =
2210          new FastStringBuffer("Wrong number of subscripts (0) for array of rank ");
2211        sb.append(array.getRank());
2212        sb.append('.');
2213        return error(new ProgramError(sb.toString()));
2214      }
2215      @Override
2216      public LispObject execute(LispObject first, LispObject second)
2217        throws ConditionThrowable
2218      {
2219        return first.AREF(second);
2220      }
2221      @Override
2222      public LispObject execute(LispObject first, LispObject second,
2223                                LispObject third)
2224        throws ConditionThrowable
2225      {
2226        return checkArray(first).get(new int[]{Fixnum.getValue(second),Fixnum.getValue(third)} );
2227      }
2228      @Override
2229      public LispObject execute(LispObject[] args) throws ConditionThrowable
2230      {
2231        final AbstractArray array = checkArray(args[0]);
2232        final int[] subs = new int[args.length - 1];
2233        for (int i = subs.length; i-- > 0;)
2234          {
2235            subs[i] = Fixnum.getValue(args[i+1]);
2236          }
2237        return array.get(subs);
2238      }
2239    };
2240
2241  // ### aset array subscripts new-element => new-element
2242  private static final Primitive ASET =
2243    new Primitive("aset", PACKAGE_SYS, true,
2244                  "array subscripts new-element")
2245    {
2246      @Override
2247      public LispObject execute(LispObject first, LispObject second)
2248        throws ConditionThrowable
2249      {
2250        // Rank zero array.
2251        final ZeroRankArray array;
2252          if (first instanceof ZeroRankArray){
2253            array = (ZeroRankArray) first;
2254          }
2255          else
2256          {
2257            return error(new TypeError("The value " +
2258                                        first.writeToString() +
2259                                        " is not an array of rank 0."));
2260          }
2261        array.aset(0, second);
2262        return second;
2263      }
2264      @Override
2265      public LispObject execute(LispObject first, LispObject second,
2266                                LispObject third)
2267        throws ConditionThrowable
2268      {
2269        first.aset(second, third);
2270        return third;
2271      }
2272      @Override
2273      public LispObject execute(LispObject[] args) throws ConditionThrowable
2274      {
2275        final AbstractArray array = checkArray(args[0]);
2276        final int nsubs = args.length - 2;
2277        final int[] subs = new int[nsubs];
2278        for (int i = nsubs; i-- > 0;)
2279            subs[i] = Fixnum.getValue(args[i+1]);
2280        final LispObject newValue = args[args.length - 1];
2281        array.set(subs, newValue);
2282        return newValue;
2283      }
2284    };
2285
2286  // ### row-major-aref array index => element
2287  private static final Primitive ROW_MAJOR_AREF =
2288    new Primitive(Symbol.ROW_MAJOR_AREF, "array index")
2289    {
2290      @Override
2291      public LispObject execute(LispObject first, LispObject second)
2292        throws ConditionThrowable
2293      {         
2294            return checkArray(first).AREF(Fixnum.getValue(second));
2295      }
2296    };
2297
2298  // ### vector
2299  private static final Primitive VECTOR =
2300    new Primitive(Symbol.VECTOR, "&rest objects")
2301    {
2302      @Override
2303      public LispObject execute(LispObject[] args) throws ConditionThrowable
2304      {
2305        return new SimpleVector(args);
2306      }
2307    };
2308
2309  // ### fill-pointer
2310  private static final Primitive FILL_POINTER =
2311    new Primitive(Symbol.FILL_POINTER, "vector")
2312    {
2313      @Override
2314      public LispObject execute(LispObject arg)
2315        throws ConditionThrowable
2316      {
2317          if (arg instanceof AbstractArray) {
2318                  AbstractArray aa = (AbstractArray)arg;
2319                  if (aa.hasFillPointer())           
2320                          return Fixnum.getInstance(aa.getFillPointer());
2321          }
2322            return type_error(arg, list(Symbol.AND, Symbol.VECTOR,
2323                                              list(Symbol.SATISFIES,
2324                                                    Symbol.ARRAY_HAS_FILL_POINTER_P)));
2325      }
2326    };
2327
2328  // ### %set-fill-pointer vector new-fill-pointer
2329  private static final Primitive _SET_FILL_POINTER =
2330    new Primitive("%set-fill-pointer", PACKAGE_SYS, true)
2331    {
2332      @Override
2333      public LispObject execute(LispObject first, LispObject second)
2334        throws ConditionThrowable
2335      {
2336
2337          if (first instanceof AbstractVector) {
2338            AbstractVector v = (AbstractVector) first;
2339            if (v.hasFillPointer())
2340              v.setFillPointer(second);
2341            else
2342              v.noFillPointer();
2343            return second;
2344          }
2345
2346            return type_error(first, list(Symbol.AND, Symbol.VECTOR,
2347                                                list(Symbol.SATISFIES,
2348                                                      Symbol.ARRAY_HAS_FILL_POINTER_P)));         
2349      }
2350    };
2351
2352  // ### vector-push new-element vector => index-of-new-element
2353  private static final Primitive VECTOR_PUSH =
2354    new Primitive(Symbol.VECTOR_PUSH, "new-element vector")
2355    {
2356      @Override
2357      public LispObject execute(LispObject first, LispObject second)
2358        throws ConditionThrowable
2359      {
2360        final AbstractVector v = checkVector(second);
2361        int fillPointer = v.getFillPointer();
2362        if (fillPointer < 0)
2363          v.noFillPointer();
2364        if (fillPointer >= v.capacity())
2365          return NIL;
2366        v.aset(fillPointer, first);
2367        v.setFillPointer(fillPointer + 1);
2368        return Fixnum.getInstance(fillPointer);
2369      }
2370    };
2371
2372  // ### vector-push-extend new-element vector &optional extension
2373  // => index-of-new-element
2374  private static final Primitive VECTOR_PUSH_EXTEND =
2375    new Primitive(Symbol.VECTOR_PUSH_EXTEND,
2376                  "new-element vector &optional extension")
2377    {
2378      @Override
2379      public LispObject execute(LispObject first, LispObject second)
2380        throws ConditionThrowable
2381      {
2382        return second.VECTOR_PUSH_EXTEND(first);
2383      }
2384
2385      @Override
2386      public LispObject execute(LispObject first, LispObject second,
2387                                LispObject third)
2388        throws ConditionThrowable
2389      {
2390        return second.VECTOR_PUSH_EXTEND(first, third);
2391      }
2392    };
2393
2394  // ### vector-pop vector => element
2395  private static final Primitive VECTOR_POP =
2396    new Primitive(Symbol.VECTOR_POP, "vector")
2397    {
2398      @Override
2399      public LispObject execute(LispObject arg) throws ConditionThrowable
2400      {
2401        final AbstractVector v = checkVector( arg);
2402        int fillPointer = v.getFillPointer();
2403        if (fillPointer < 0)
2404          v.noFillPointer();
2405        if (fillPointer == 0)
2406          error(new LispError("nothing left to pop"));
2407        int newFillPointer = v.checkIndex(fillPointer - 1);
2408        LispObject element = v.AREF(newFillPointer);
2409        v.setFillPointer(newFillPointer);
2410        return element;
2411      }
2412    };
2413
2414  // ### type-of
2415  private static final Primitive TYPE_OF =
2416    new Primitive(Symbol.TYPE_OF, "object")
2417    {
2418      @Override
2419      public LispObject execute(LispObject arg) throws ConditionThrowable
2420      {
2421        return arg.typeOf();
2422      }
2423    };
2424
2425  // ### class-of
2426  private static final Primitive CLASS_OF =
2427    new Primitive(Symbol.CLASS_OF, "object")
2428    {
2429      @Override
2430      public LispObject execute(LispObject arg) throws ConditionThrowable
2431      {
2432        return arg.classOf();
2433      }
2434    };
2435
2436  // ### simple-typep
2437  private static final Primitive SIMPLE_TYPEP =
2438    new Primitive("simple-typep", PACKAGE_SYS, true)
2439    {
2440      @Override
2441      public LispObject execute(LispObject first, LispObject second)
2442        throws ConditionThrowable
2443      {
2444        return first.typep(second);
2445      }
2446    };
2447
2448  // ### function-lambda-expression function =>
2449  // lambda-expression, closure-p, name
2450  private static final Primitive FUNCTION_LAMBDA_EXPRESSION =
2451    new Primitive(Symbol.FUNCTION_LAMBDA_EXPRESSION, "function")
2452    {
2453      @Override
2454      public LispObject execute(LispObject arg) throws ConditionThrowable
2455      {
2456        final LispObject value1, value2, value3;
2457        if (arg instanceof CompiledClosure)
2458          {
2459            value1 = NIL;
2460            value2 = T;
2461            LispObject name = ((CompiledClosure)arg).getLambdaName();
2462            value3 = name != null ? name : NIL;
2463          }
2464        else if (arg instanceof Closure)
2465          {
2466            Closure closure = (Closure) arg;
2467            LispObject expr = closure.getBody();
2468            expr = new Cons(closure.getLambdaList(), expr);
2469            expr = new Cons(Symbol.LAMBDA, expr);
2470            value1 = expr;
2471            Environment env = closure.getEnvironment();
2472            if (env == null || env.isEmpty())
2473              value2 = NIL;
2474            else
2475              value2 = env; // Return environment as closure-p.
2476            LispObject name = ((Closure)arg).getLambdaName();
2477            value3 = name != null ? name : NIL;
2478          }
2479        else if (arg instanceof Function)
2480          {
2481            value1 = NIL;
2482            value2 = T;
2483            value3 = ((Function)arg).getLambdaName();
2484          }
2485        else if (arg instanceof StandardGenericFunction)
2486          {
2487            value1 = NIL;
2488            value2 = T;
2489            value3 = ((StandardGenericFunction)arg).getGenericFunctionName();
2490          }
2491        else
2492          return type_error(arg, Symbol.FUNCTION);
2493        return LispThread.currentThread().setValues(value1, value2, value3);
2494      }
2495    };
2496
2497  // ### funcall
2498  // This needs to be public for LispAPI.java.
2499  public static final Primitive FUNCALL =
2500    new Primitive(Symbol.FUNCALL, "function &rest args")
2501    {
2502      @Override
2503      public LispObject execute() throws ConditionThrowable
2504      {
2505        return error(new WrongNumberOfArgumentsException(this));
2506      }
2507      @Override
2508      public LispObject execute(LispObject arg) throws ConditionThrowable
2509      {
2510        return LispThread.currentThread().execute(arg);
2511      }
2512      @Override
2513      public LispObject execute(LispObject first, LispObject second)
2514        throws ConditionThrowable
2515      {
2516        return LispThread.currentThread().execute(first, second);
2517      }
2518      @Override
2519      public LispObject execute(LispObject first, LispObject second,
2520                                LispObject third)
2521        throws ConditionThrowable
2522      {
2523        return LispThread.currentThread().execute(first, second, third);
2524      }
2525      @Override
2526      public LispObject execute(LispObject first, LispObject second,
2527                                LispObject third, LispObject fourth)
2528        throws ConditionThrowable
2529      {
2530        return LispThread.currentThread().execute(first, second, third,
2531                                                  fourth);
2532      }
2533      @Override
2534      public LispObject execute(LispObject first, LispObject second,
2535                                LispObject third, LispObject fourth,
2536                                LispObject fifth)
2537        throws ConditionThrowable
2538      {
2539        return LispThread.currentThread().execute(first, second, third,
2540                                                  fourth, fifth);
2541      }
2542      @Override
2543      public LispObject execute(LispObject first, LispObject second,
2544                                LispObject third, LispObject fourth,
2545                                LispObject fifth, LispObject sixth)
2546        throws ConditionThrowable
2547      {
2548        return LispThread.currentThread().execute(first, second, third,
2549                                                  fourth, fifth, sixth);
2550      }
2551      @Override
2552      public LispObject execute(LispObject first, LispObject second,
2553                                LispObject third, LispObject fourth,
2554                                LispObject fifth, LispObject sixth,
2555                                LispObject seventh)
2556        throws ConditionThrowable
2557      {
2558        return LispThread.currentThread().execute(first, second, third,
2559                                                  fourth, fifth, sixth,
2560                                                  seventh);
2561      }
2562      @Override
2563      public LispObject execute(LispObject first, LispObject second,
2564                                LispObject third, LispObject fourth,
2565                                LispObject fifth, LispObject sixth,
2566                                LispObject seventh, LispObject eigth)
2567        throws ConditionThrowable
2568      {
2569        return LispThread.currentThread().execute(first, second, third,
2570                                                  fourth, fifth, sixth,
2571                                                  seventh, eigth);
2572      }
2573      @Override
2574      public LispObject execute(LispObject[] args) throws ConditionThrowable
2575      {
2576        final int length = args.length - 1; // Number of arguments.
2577        if (length == 8)
2578          {
2579            return LispThread.currentThread().execute(args[0], args[1],
2580                                                      args[2], args[3],
2581                                                      args[4], args[5],
2582                                                      args[6], args[7],
2583                                                      args[8]);
2584          }
2585        else
2586          {
2587            LispObject[] newArgs = new LispObject[length];
2588            System.arraycopy(args, 1, newArgs, 0, length);
2589            return LispThread.currentThread().execute(args[0], newArgs);
2590          }
2591      }
2592    };
2593
2594  // ### apply
2595  public static final Primitive APPLY =
2596    new Primitive(Symbol.APPLY, "function &rest args")
2597    {
2598      @Override
2599      public LispObject execute() throws ConditionThrowable
2600      {
2601        return error(new WrongNumberOfArgumentsException(this));
2602      }
2603      @Override
2604      public LispObject execute(LispObject arg) throws ConditionThrowable
2605      {
2606        return error(new WrongNumberOfArgumentsException(this));
2607      }
2608      @Override
2609      public LispObject execute(LispObject fun, LispObject args)
2610        throws ConditionThrowable
2611      {
2612        final LispThread thread = LispThread.currentThread();
2613        final int length = args.length();
2614        switch (length)
2615          {
2616          case 0:
2617            return thread.execute(fun);
2618          case 1:
2619            return thread.execute(fun, ((Cons)args).car);
2620          case 2:
2621            {
2622              Cons cons = (Cons) args;
2623              return thread.execute(fun, cons.car, ((Cons)cons.cdr).car);
2624            }
2625          case 3:
2626            return thread.execute(fun, args.car(), args.cadr(),
2627                                  args.cdr().cdr().car());
2628          default:
2629            {
2630              final LispObject[] funArgs = new LispObject[length];
2631              int j = 0;
2632              while (args != NIL)
2633                {
2634                  funArgs[j++] = args.car();
2635                  args = args.cdr();
2636                }
2637              return funcall(fun, funArgs, thread);
2638            }
2639          }
2640      }
2641      @Override
2642      public LispObject execute(LispObject first, LispObject second,
2643                                LispObject third)
2644        throws ConditionThrowable
2645      {
2646        if (third.listp())
2647          {
2648            final int numFunArgs = 1 + third.length();
2649            final LispObject[] funArgs = new LispObject[numFunArgs];
2650            funArgs[0] = second;
2651            int j = 1;
2652            while (third != NIL)
2653              {
2654                funArgs[j++] = third.car();
2655                third = third.cdr();
2656              }
2657            return funcall(first, funArgs, LispThread.currentThread());
2658          }
2659        return type_error(third, Symbol.LIST);
2660      }
2661      @Override
2662      public LispObject execute(final LispObject[] args) throws ConditionThrowable
2663      {
2664        final int numArgs = args.length;
2665        LispObject spread = args[numArgs - 1];
2666        if (spread.listp())
2667          {
2668            final int numFunArgs = numArgs - 2 + spread.length();
2669            final LispObject[] funArgs = new LispObject[numFunArgs];
2670            int j = 0;
2671            for (int i = 1; i < numArgs - 1; i++)
2672              funArgs[j++] = args[i];
2673            while (spread != NIL)
2674              {
2675                funArgs[j++] = spread.car();
2676                spread = spread.cdr();
2677              }
2678            return funcall(args[0], funArgs, LispThread.currentThread());
2679          }
2680        return type_error(spread, Symbol.LIST);
2681      }
2682    };
2683
2684  // ### mapcar
2685  private static final Primitive MAPCAR =
2686    new Primitive(Symbol.MAPCAR, "function &rest lists")
2687    {
2688      @Override
2689      public LispObject execute(LispObject fun, LispObject list)
2690        throws ConditionThrowable
2691      {
2692        final LispThread thread = LispThread.currentThread();
2693        LispObject result = NIL;
2694        Cons splice = null;
2695        while (list != NIL)
2696          {
2697            Cons cons;
2698            if (list instanceof Cons)
2699                cons = (Cons) list;
2700            else
2701                return type_error(list, Symbol.LIST);
2702            LispObject obj = thread.execute(fun, cons.car);
2703            if (splice == null)
2704              {
2705                splice = new Cons(obj, result);
2706                result = splice;
2707              }
2708            else
2709              {
2710                Cons c = new Cons(obj);
2711                splice.cdr = c;
2712                splice = c;
2713              }
2714            list = cons.cdr;
2715          }
2716        thread._values = null;
2717        return result;
2718      }
2719      @Override
2720      public LispObject execute(LispObject fun, LispObject list1,
2721                                LispObject list2)
2722        throws ConditionThrowable
2723      {
2724        final LispThread thread = LispThread.currentThread();
2725        LispObject result = NIL;
2726        Cons splice = null;
2727        while (list1 != NIL && list2 != NIL)
2728          {
2729            LispObject obj =
2730              thread.execute(fun, list1.car(), list2.car());
2731            if (splice == null)
2732              {
2733                splice = new Cons(obj, result);
2734                result = splice;
2735              }
2736            else
2737              {
2738                Cons cons = new Cons(obj);
2739                splice.cdr = cons;
2740                splice = cons;
2741              }
2742            list1 = list1.cdr();
2743            list2 = list2.cdr();
2744          }
2745        thread._values = null;
2746        return result;
2747      }
2748      @Override
2749      public LispObject execute(final LispObject[] args)
2750        throws ConditionThrowable
2751      {
2752        final int numArgs = args.length;
2753        if (numArgs < 2)
2754          return error(new WrongNumberOfArgumentsException(this));
2755        int commonLength = -1;
2756        for (int i = 1; i < numArgs; i++)
2757          {
2758            if (!args[i].listp())
2759              type_error(args[i], Symbol.LIST);
2760            int len = args[i].length();
2761            if (commonLength < 0)
2762              commonLength = len;
2763            else if (commonLength > len)
2764              commonLength = len;
2765          }
2766        final LispThread thread = LispThread.currentThread();
2767        LispObject[] results = new LispObject[commonLength];
2768        final int numFunArgs = numArgs - 1;
2769        final LispObject[] funArgs = new LispObject[numFunArgs];
2770        for (int i = 0; i < commonLength; i++)
2771          {
2772            for (int j = 0; j < numFunArgs; j++)
2773              funArgs[j] = args[j+1].car();
2774            results[i] = funcall(args[0], funArgs, thread);
2775            for (int j = 1; j < numArgs; j++)
2776              args[j] = args[j].cdr();
2777          }
2778        thread._values = null;
2779        LispObject result = NIL;
2780        for (int i = commonLength; i-- > 0;)
2781          result = new Cons(results[i], result);
2782        return result;
2783      }
2784    };
2785
2786  // ### mapc
2787  private static final Primitive MAPC =
2788    new Primitive(Symbol.MAPC, "function &rest lists")
2789    {
2790      @Override
2791      public LispObject execute(LispObject fun, LispObject list)
2792        throws ConditionThrowable
2793      {
2794        final LispThread thread = LispThread.currentThread();
2795        LispObject result = list;
2796        while (list != NIL)
2797          {
2798            Cons cons;
2799            if (list instanceof Cons)
2800                cons = (Cons) list;
2801            else
2802                return type_error(list, Symbol.LIST);
2803            thread.execute(fun, cons.car);
2804            list = cons.cdr;
2805          }
2806        thread._values = null;
2807        return result;
2808      }
2809      @Override
2810      public LispObject execute(LispObject fun, LispObject list1,
2811                                LispObject list2)
2812        throws ConditionThrowable
2813      {
2814        final LispThread thread = LispThread.currentThread();
2815        LispObject result = list1;
2816        while (list1 != NIL && list2 != NIL)
2817          {
2818            thread.execute(fun, list1.car(), list2.car());
2819            list1 = ((Cons)list1).cdr;
2820            list2 = ((Cons)list2).cdr;
2821          }
2822        thread._values = null;
2823        return result;
2824      }
2825      @Override
2826      public LispObject execute(final LispObject[] args)
2827        throws ConditionThrowable
2828      {
2829        final int numArgs = args.length;
2830        if (numArgs < 2)
2831          return error(new WrongNumberOfArgumentsException(this));
2832        int commonLength = -1;
2833        for (int i = 1; i < numArgs; i++)
2834          {
2835            if (!args[i].listp())
2836              type_error(args[i], Symbol.LIST);
2837            int len = args[i].length();
2838            if (commonLength < 0)
2839              commonLength = len;
2840            else if (commonLength > len)
2841              commonLength = len;
2842          }
2843        final LispThread thread = LispThread.currentThread();
2844        LispObject result = args[1];
2845        final int numFunArgs = numArgs - 1;
2846        final LispObject[] funArgs = new LispObject[numFunArgs];
2847        for (int i = 0; i < commonLength; i++)
2848          {
2849            for (int j = 0; j < numFunArgs; j++)
2850              funArgs[j] = args[j+1].car();
2851            funcall(args[0], funArgs, thread);
2852            for (int j = 1; j < numArgs; j++)
2853              args[j] = args[j].cdr();
2854          }
2855        thread._values = null;
2856        return result;
2857      }
2858    };
2859
2860  // ### macroexpand
2861  private static final Primitive MACROEXPAND =
2862    new Primitive(Symbol.MACROEXPAND, "form &optional env")
2863    {
2864      @Override
2865      public LispObject execute(LispObject form) throws ConditionThrowable
2866      {
2867        return macroexpand(form,
2868                           new Environment(),
2869                           LispThread.currentThread());
2870      }
2871      @Override
2872      public LispObject execute(LispObject form, LispObject env)
2873        throws ConditionThrowable
2874      {
2875        return macroexpand(form,
2876                           env != NIL ? checkEnvironment(env) : new Environment(),
2877                           LispThread.currentThread());
2878      }
2879    };
2880
2881  // ### macroexpand-1
2882  private static final Primitive MACROEXPAND_1 =
2883    new Primitive(Symbol.MACROEXPAND_1, "form &optional env")
2884    {
2885      @Override
2886      public LispObject execute(LispObject form) throws ConditionThrowable
2887      {
2888        return macroexpand_1(form,
2889                             new Environment(),
2890                             LispThread.currentThread());
2891      }
2892      @Override
2893      public LispObject execute(LispObject form, LispObject env)
2894        throws ConditionThrowable
2895      {
2896        return macroexpand_1(form,
2897                             env != NIL ? checkEnvironment(env) : new Environment(),
2898                             LispThread.currentThread());
2899      }
2900    };
2901
2902  // ### gensym
2903  private static final Primitive GENSYM =
2904    new Primitive(Symbol.GENSYM, "&optional x")
2905    {
2906      @Override
2907      public LispObject execute() throws ConditionThrowable
2908      {
2909        return gensym("G", LispThread.currentThread());
2910      }
2911      @Override
2912      public LispObject execute(LispObject arg) throws ConditionThrowable
2913      {
2914        if (arg instanceof Fixnum)
2915          {
2916            int n = ((Fixnum)arg).value;
2917            if (n >= 0)
2918              {
2919                FastStringBuffer sb = new FastStringBuffer('G');
2920                sb.append(n); // Decimal representation.
2921                return new Symbol(new SimpleString(sb));
2922              }
2923          }
2924        else if (arg instanceof Bignum)
2925          {
2926            BigInteger n = ((Bignum)arg).value;
2927            if (n.signum() >= 0)
2928              {
2929                FastStringBuffer sb = new FastStringBuffer('G');
2930                sb.append(n.toString()); // Decimal representation.
2931                return new Symbol(new SimpleString(sb));
2932              }
2933          }
2934        else if (arg instanceof AbstractString)
2935          return gensym(arg.getStringValue(), LispThread.currentThread());
2936        return type_error(arg,
2937                               list(Symbol.OR,
2938                                     Symbol.STRING,
2939                                     Symbol.UNSIGNED_BYTE));
2940      }
2941    };
2942
2943  // ### string
2944  private static final Primitive STRING = new Primitive(Symbol.STRING, "x")
2945    {
2946      @Override
2947      public LispObject execute(LispObject arg) throws ConditionThrowable
2948      {
2949        return arg.STRING();
2950      }
2951    };
2952
2953  // ### intern string &optional package => symbol, status
2954  // STATUS is one of :INHERITED, :EXTERNAL, :INTERNAL or NIL.
2955  // "It is implementation-dependent whether the string that becomes the new
2956  // symbol's name is the given string or a copy of it."
2957  private static final Primitive INTERN =
2958    new Primitive(Symbol.INTERN, "string &optional package")
2959    {
2960      @Override
2961      public LispObject execute(LispObject arg) throws ConditionThrowable
2962      {
2963        final SimpleString s;
2964        if (arg instanceof SimpleString)
2965          s = (SimpleString) arg;
2966        else
2967          s = new SimpleString(arg.getStringValue());
2968        final LispThread thread = LispThread.currentThread();
2969        Package pkg = (Package) Symbol._PACKAGE_.symbolValue(thread);
2970        return pkg.intern(s, thread);
2971      }
2972      @Override
2973      public LispObject execute(LispObject first, LispObject second)
2974        throws ConditionThrowable
2975      {
2976        final SimpleString s;
2977        if (first instanceof SimpleString)
2978          s = (SimpleString) first;
2979        else
2980          s = new SimpleString(first.getStringValue());
2981        Package pkg = coerceToPackage(second);
2982        return pkg.intern(s, LispThread.currentThread());
2983      }
2984    };
2985
2986  // ### unintern
2987  // unintern symbol &optional package => generalized-boolean
2988  private static final Primitive UNINTERN =
2989    new Primitive(Symbol.UNINTERN, "symbol &optional package")
2990    {
2991      @Override
2992      public LispObject execute(LispObject[] args) throws ConditionThrowable
2993      {
2994        if (args.length == 0 || args.length > 2)
2995          return error(new WrongNumberOfArgumentsException(this));
2996        Symbol symbol = checkSymbol(args[0]);
2997        Package pkg;
2998        if (args.length == 2)
2999          pkg = coerceToPackage(args[1]);
3000        else
3001          pkg = getCurrentPackage();
3002        return pkg.unintern(symbol);
3003      }
3004    };
3005
3006  // ### find-package
3007  private static final Primitive FIND_PACKAGE =
3008    new Primitive(Symbol.FIND_PACKAGE, "name")
3009    {
3010      @Override
3011      public LispObject execute(LispObject arg) throws ConditionThrowable
3012      {
3013        if (arg instanceof Package)
3014          return arg;
3015        if (arg instanceof AbstractString)
3016          {
3017            Package pkg =
3018              Packages.findPackage(arg.getStringValue());
3019            return pkg != null ? pkg : NIL;
3020          }
3021        if (arg instanceof Symbol)
3022          {
3023            Package pkg = Packages.findPackage(checkSymbol(arg).getName());
3024            return pkg != null ? pkg : NIL;
3025          }
3026        if (arg instanceof LispCharacter)
3027          {
3028            String packageName =
3029              String.valueOf(new char[] {((LispCharacter)arg).getValue()});
3030            Package pkg = Packages.findPackage(packageName);
3031            return pkg != null ? pkg : NIL;
3032          }
3033        return NIL;
3034      }
3035    };
3036
3037  // ### %make-package
3038  // %make-package package-name nicknames use => package
3039  private static final Primitive _MAKE_PACKAGE =
3040    new Primitive("%make-package", PACKAGE_SYS, false)
3041    {
3042      /**
3043       * This invocation is solely used to be able to create
3044       * a package to bind to *FASL-ANONYMOUS-PACKAGE*
3045       */
3046      @Override
3047      public LispObject execute()
3048        throws ConditionThrowable
3049      {
3050        return new Package();
3051      }
3052
3053      /**
3054       * This invocation is used by MAKE-PACKAGE to create a package
3055       */
3056      @Override
3057      public LispObject execute(LispObject first, LispObject second,
3058                                LispObject third)
3059        throws ConditionThrowable
3060      {
3061        String packageName = javaString(first);
3062        Package pkg = Packages.findPackage(packageName);
3063        if (pkg != null)
3064          error(new LispError("Package " + packageName +
3065                               " already exists."));
3066        LispObject nicknames = checkList(second);
3067        if (nicknames != NIL)
3068          {
3069            LispObject list = nicknames;
3070            while (list != NIL)
3071              {
3072                String nick = javaString(list.car());
3073                if (Packages.findPackage(nick) != null)
3074                  {
3075                    error(new PackageError("A package named " + nick +
3076                                            " already exists."));
3077                  }
3078                list = list.cdr();
3079              }
3080          }
3081        LispObject use = checkList(third);
3082        if (use != NIL)
3083          {
3084            LispObject list = use;
3085            while (list != NIL)
3086              {
3087                LispObject obj = list.car();
3088                if (obj instanceof Package) {
3089                  // OK.
3090                } else
3091                  {
3092                    String s = javaString(obj);
3093                    Package p = Packages.findPackage(s);
3094                    if (p == null)
3095                      {
3096                        error(new LispError(obj.writeToString() +
3097                                             " is not the name of a package."));
3098                        return NIL;
3099                      }
3100                  }
3101                list = list.cdr();
3102              }
3103          }
3104        // Now create the package.
3105        pkg = Packages.createPackage(packageName);
3106        // Add the nicknames.
3107        while (nicknames != NIL)
3108          {
3109            String nick = javaString(nicknames.car());
3110            pkg.addNickname(nick);
3111            nicknames = nicknames.cdr();
3112          }
3113        // Create the use list.
3114        while (use != NIL)
3115          {
3116            LispObject obj = use.car();
3117            if (obj instanceof Package)
3118              pkg.usePackage((Package)obj);
3119            else
3120              {
3121                String s = javaString(obj);
3122                Package p = Packages.findPackage(s);
3123                if (p == null)
3124                  {
3125                    error(new LispError(obj.writeToString() +
3126                                         " is not the name of a package."));
3127                    return NIL;
3128                  }
3129                pkg.usePackage(p);
3130              }
3131            use = use.cdr();
3132          }
3133        return pkg;
3134      }
3135    };
3136
3137  // ### %in-package
3138  private static final Primitive _IN_PACKAGE =
3139    new Primitive("%in-package", PACKAGE_SYS, true)
3140    {
3141      @Override
3142      public LispObject execute(LispObject arg) throws ConditionThrowable
3143      {
3144        final String packageName = javaString(arg);
3145        final Package pkg = Packages.findPackage(packageName);
3146        if (pkg == null)
3147          return error(new PackageError("The name " + packageName +
3148                                         " does not designate any package."));
3149        SpecialBinding binding =
3150          LispThread.currentThread().getSpecialBinding(Symbol._PACKAGE_);
3151        if (binding != null)
3152          binding.value = pkg;
3153        else
3154          // No dynamic binding.
3155          Symbol._PACKAGE_.setSymbolValue(pkg);
3156        return pkg;
3157      }
3158    };
3159
3160  // ### use-package packages-to-use &optional package => t
3161  private static final Primitive USE_PACKAGE =
3162    new Primitive(Symbol.USE_PACKAGE, "packages-to-use &optional package")
3163    {
3164      @Override
3165      public LispObject execute(LispObject[] args) throws ConditionThrowable
3166      {
3167        if (args.length < 1 || args.length > 2)
3168          return error(new WrongNumberOfArgumentsException(this));
3169        Package pkg;
3170        if (args.length == 2)
3171          pkg = coerceToPackage(args[1]);
3172        else
3173          pkg = getCurrentPackage();
3174        if (args[0].listp())
3175          {
3176            LispObject list = args[0];
3177            while (list != NIL)
3178              {
3179                pkg.usePackage(coerceToPackage(list.car()));
3180                list = list.cdr();
3181              }
3182          }
3183        else
3184          pkg.usePackage(coerceToPackage(args[0]));
3185        return T;
3186      }
3187    };
3188
3189  // ### package-symbols
3190  private static final Primitive PACKAGE_SYMBOLS =
3191    new Primitive("package-symbols", PACKAGE_SYS, true)
3192    {
3193      @Override
3194      public LispObject execute(LispObject arg) throws ConditionThrowable
3195      {
3196        return coerceToPackage(arg).getSymbols();
3197      }
3198    };
3199
3200  // ### package-internal-symbols
3201  private static final Primitive PACKAGE_INTERNAL_SYMBOLS =
3202    new Primitive("package-internal-symbols", PACKAGE_SYS, true)
3203    {
3204      @Override
3205      public LispObject execute(LispObject arg) throws ConditionThrowable
3206      {
3207        return coerceToPackage(arg).PACKAGE_INTERNAL_SYMBOLS();
3208      }
3209    };
3210
3211  // ### package-external-symbols
3212  private static final Primitive PACKAGE_EXTERNAL_SYMBOLS =
3213    new Primitive("package-external-symbols", PACKAGE_SYS, true)
3214    {
3215      @Override
3216      public LispObject execute(LispObject arg) throws ConditionThrowable
3217      {
3218        return coerceToPackage(arg).PACKAGE_EXTERNAL_SYMBOLS();
3219      }
3220    };
3221
3222  // ### package-inherited-symbols
3223  private static final Primitive PACKAGE_INHERITED_SYMBOLS =
3224    new Primitive("package-inherited-symbols", PACKAGE_SYS, true)
3225    {
3226      @Override
3227      public LispObject execute(LispObject arg) throws ConditionThrowable
3228      {
3229        return coerceToPackage(arg).PACKAGE_INHERITED_SYMBOLS();
3230      }
3231    };
3232
3233  // ### export symbols &optional package
3234  private static final Primitive EXPORT =
3235    new Primitive(Symbol.EXPORT, "symbols &optional package")
3236    {
3237      @Override
3238      public LispObject execute(LispObject arg) throws ConditionThrowable
3239      {
3240        final Package pkg = (Package) Symbol._PACKAGE_.symbolValue();
3241        if (arg instanceof Cons)
3242          {
3243            for (LispObject list = arg; list != NIL; list = list.cdr())
3244              pkg.export(checkSymbol(list.car()));
3245          }
3246        else
3247          pkg.export(checkSymbol(arg));
3248        return T;
3249      }
3250
3251      @Override
3252      public LispObject execute(LispObject first, LispObject second)
3253        throws ConditionThrowable
3254      {
3255        if (first instanceof Cons)
3256          {
3257            Package pkg = coerceToPackage(second);
3258            for (LispObject list = first; list != NIL; list = list.cdr())
3259              pkg.export(checkSymbol(list.car()));
3260          }
3261        else
3262          coerceToPackage(second).export(checkSymbol(first));
3263        return T;
3264      }
3265    };
3266
3267  // ### find-symbol string &optional package => symbol, status
3268  private static final Primitive FIND_SYMBOL =
3269    new Primitive(Symbol.FIND_SYMBOL, "string &optional package")
3270    {
3271      @Override
3272      public LispObject execute(LispObject arg) throws ConditionThrowable
3273      {
3274        return getCurrentPackage().findSymbol(arg.getStringValue());
3275      }
3276
3277      @Override
3278      public LispObject execute(LispObject first, LispObject second)
3279        throws ConditionThrowable
3280      {
3281        return coerceToPackage(second).findSymbol(first.getStringValue());
3282      }
3283    };
3284
3285  // ### fset name function &optional source-position arglist documentation
3286  // => function
3287  private static final Primitive FSET =
3288    new Primitive("fset", PACKAGE_SYS, true)
3289    {
3290      @Override
3291      public LispObject execute(LispObject first, LispObject second)
3292        throws ConditionThrowable
3293      {
3294        return execute(first, second, NIL, NIL, NIL);
3295      }
3296      @Override
3297      public LispObject execute(LispObject first, LispObject second,
3298                                LispObject third)
3299        throws ConditionThrowable
3300      {
3301        return execute(first, second, third, NIL, NIL);
3302      }
3303      @Override
3304      public LispObject execute(LispObject first, LispObject second,
3305                                LispObject third, LispObject fourth)
3306        throws ConditionThrowable
3307      {
3308        return execute(first, second, third, fourth, NIL);
3309      }
3310      @Override
3311      public LispObject execute(LispObject first, LispObject second,
3312                                LispObject third, LispObject fourth,
3313                                LispObject fifth)
3314        throws ConditionThrowable
3315      {
3316        if (first instanceof Symbol)
3317          {
3318            checkRedefinition(first);
3319            Symbol symbol = checkSymbol(first);
3320            symbol.setSymbolFunction(second);
3321            final LispThread thread = LispThread.currentThread();
3322            LispObject sourcePathname = _SOURCE_.symbolValue(thread);
3323            LispObject sourcePosition = third;
3324            if (sourcePathname != NIL)
3325              sourcePosition = _SOURCE_POSITION_.symbolValue(thread);
3326            if (sourcePathname == NIL)
3327              sourcePathname = Keyword.TOP_LEVEL;
3328            if (sourcePathname != Keyword.TOP_LEVEL)
3329              put(symbol, Symbol._SOURCE, new Cons(sourcePathname, third));
3330            else
3331              put(symbol, Symbol._SOURCE, sourcePathname);
3332          }
3333        else if (isValidSetfFunctionName(first))
3334          {
3335            // SETF function
3336            checkRedefinition(first);
3337            Symbol symbol = checkSymbol(first.cadr());
3338            put(symbol, Symbol.SETF_FUNCTION, second);
3339          }
3340        else
3341          return type_error(first, FUNCTION_NAME);
3342        if (second instanceof Operator)
3343          {
3344            Operator op = (Operator) second;
3345            op.setLambdaName(first);
3346            if (fourth != NIL)
3347              op.setLambdaList(fourth);
3348            if (fifth != NIL)
3349              op.setDocumentation(Symbol.FUNCTION, fifth);
3350          }
3351        return second;
3352      }
3353    };
3354
3355  // ### %set-symbol-plist
3356  private static final Primitive _SET_SYMBOL_PLIST =
3357    new Primitive("%set-symbol-plist", PACKAGE_SYS, false)
3358    {
3359      @Override
3360      public LispObject execute(LispObject first, LispObject second)
3361        throws ConditionThrowable
3362      {
3363        checkSymbol(first).setPropertyList(checkList(second));
3364        return second;
3365      }
3366    };
3367
3368  // ### getf plist indicator &optional default => value
3369  private static final Primitive GETF =
3370    new Primitive(Symbol.GETF, "plist indicator &optional default")
3371    {
3372      @Override
3373      public LispObject execute(LispObject plist, LispObject indicator)
3374        throws ConditionThrowable
3375      {
3376        return getf(plist, indicator, NIL);
3377      }
3378      @Override
3379      public LispObject execute(LispObject plist, LispObject indicator,
3380                                LispObject defaultValue)
3381        throws ConditionThrowable
3382      {
3383        return getf(plist, indicator, defaultValue);
3384      }
3385    };
3386
3387  // ### get symbol indicator &optional default => value
3388  private static final Primitive GET =
3389    new Primitive(Symbol.GET, "symbol indicator &optional default")
3390    {
3391      @Override
3392      public LispObject execute(LispObject symbol, LispObject indicator)
3393        throws ConditionThrowable
3394      {
3395        return get(symbol, indicator, NIL);
3396      }
3397      @Override
3398      public LispObject execute(LispObject symbol, LispObject indicator,
3399                                LispObject defaultValue)
3400        throws ConditionThrowable
3401      {
3402        return get(symbol, indicator, defaultValue);
3403      }
3404    };
3405
3406  // ### put symbol indicator value => value
3407  private static final Primitive PUT =
3408    new Primitive("put", PACKAGE_SYS, true)
3409    {
3410      @Override
3411      public LispObject execute(LispObject symbol, LispObject indicator,
3412                                LispObject value)
3413        throws ConditionThrowable
3414      {
3415            return put(checkSymbol(symbol), indicator, value);
3416      }
3417      @Override
3418      public LispObject execute(LispObject symbol, LispObject indicator,
3419                                LispObject defaultValue, LispObject value)
3420        throws ConditionThrowable
3421      {
3422          return put(checkSymbol(symbol), indicator, value);
3423      }
3424    };
3425
3426  // ### macrolet
3427  private static final SpecialOperator MACROLET =
3428    new SpecialOperator(Symbol.MACROLET, "definitions &rest body")
3429    {
3430      @Override
3431      public LispObject execute(LispObject args, Environment env)
3432        throws ConditionThrowable
3433      {
3434        LispObject defs = checkList(args.car());
3435        final LispThread thread = LispThread.currentThread();
3436        final SpecialBinding lastSpecialBinding = thread.lastSpecialBinding;
3437
3438        try
3439          {
3440            Environment ext = new Environment(env);
3441            while (defs != NIL)
3442              {
3443                LispObject def = checkList(defs.car());
3444                Symbol symbol = checkSymbol(def.car());
3445                Symbol make_expander_for_macrolet =
3446                  PACKAGE_SYS.intern("MAKE-EXPANDER-FOR-MACROLET");
3447                LispObject expander =
3448                  make_expander_for_macrolet.execute(def);
3449                Closure expansionFunction = new Closure(expander, env);
3450                MacroObject macroObject =
3451                  new MacroObject(symbol, expansionFunction);
3452                ext.addFunctionBinding(symbol, macroObject);
3453                defs = defs.cdr();
3454              }
3455            return progn(ext.processDeclarations(args.cdr()), ext, thread);
3456          }
3457        finally
3458          {
3459            thread.lastSpecialBinding = lastSpecialBinding;
3460          }
3461      }
3462    };
3463
3464  private static final Primitive MAKE_EXPANDER_FOR_MACROLET =
3465    new Primitive("make-expander-for-macrolet", PACKAGE_SYS, true,
3466                  "definition")
3467    {
3468      @Override
3469      public LispObject execute(LispObject definition)
3470        throws ConditionThrowable
3471      {
3472        Symbol symbol = checkSymbol(definition.car());
3473        LispObject lambdaList = definition.cadr();
3474        LispObject body = definition.cddr();
3475        LispObject block =
3476          new Cons(Symbol.BLOCK, new Cons(symbol, body));
3477        LispObject toBeApplied =
3478          list(Symbol.LAMBDA, lambdaList, block);
3479        final LispThread thread = LispThread.currentThread();
3480        LispObject formArg = gensym("WHOLE-", thread);
3481        LispObject envArg = gensym("ENVIRONMENT-", thread); // Ignored.
3482        LispObject expander =
3483          list(Symbol.LAMBDA, list(formArg, envArg),
3484                list(Symbol.APPLY, toBeApplied,
3485                      list(Symbol.CDR, formArg)));
3486        return expander;
3487      }
3488    };
3489
3490  // ### tagbody
3491  private static final SpecialOperator TAGBODY =
3492    new SpecialOperator(Symbol.TAGBODY, "&rest statements")
3493    {
3494      @Override
3495      public LispObject execute(LispObject args, Environment env)
3496        throws ConditionThrowable
3497      {
3498        Environment ext = new Environment(env);
3499        LispObject localTags = NIL; // Tags that are local to this TAGBODY.
3500        LispObject body = args;
3501        while (body != NIL)
3502          {
3503            LispObject current = body.car();
3504            body = ((Cons)body).cdr;
3505            if (current instanceof Cons)
3506              continue;
3507            // It's a tag.
3508            ext.addTagBinding(current, body);
3509            localTags = new Cons(current, localTags);
3510          }
3511        final LispThread thread = LispThread.currentThread();
3512        LispObject remaining = args;
3513        while (remaining != NIL)
3514          {
3515            LispObject current = remaining.car();
3516            if (current instanceof Cons)
3517              {
3518                try
3519                  {
3520                    // Handle GO inline if possible.
3521                    if (((Cons)current).car == Symbol.GO)
3522                      {
3523                        if (interrupted)
3524                          handleInterrupt();
3525                        LispObject tag = current.cadr();
3526                        if (memql(tag, localTags))
3527                          {
3528                            Binding binding = ext.getTagBinding(tag);
3529                            if (binding != null && binding.value != null)
3530                              {
3531                                remaining = binding.value;
3532                                continue;
3533                              }
3534                          }
3535                        throw new Go(tag);
3536                      }
3537                    eval(current, ext, thread);
3538                  }
3539                catch (Go go)
3540                  {
3541                    LispObject tag = go.getTag();
3542                    if (memql(tag, localTags))
3543                      {
3544                        Binding binding = ext.getTagBinding(tag);
3545                        if (binding != null && binding.value != null)
3546                          {
3547                            remaining = binding.value;
3548                            continue;
3549                          }
3550                      }
3551                    throw go;
3552                  }
3553              }
3554            remaining = ((Cons)remaining).cdr;
3555          }
3556        thread._values = null;
3557        return NIL;
3558      }
3559    };
3560
3561  // ### go
3562  private static final SpecialOperator GO =
3563    new SpecialOperator(Symbol.GO, "tag")
3564    {
3565      @Override
3566      public LispObject execute(LispObject args, Environment env)
3567        throws ConditionThrowable
3568      {
3569        if (args.length() != 1)
3570          return error(new WrongNumberOfArgumentsException(this));
3571        Binding binding = env.getTagBinding(args.car());
3572        if (binding == null)
3573          return error(new ControlError("No tag named " +
3574                                         args.car().writeToString() +
3575                                         " is currently visible."));
3576        throw new Go(args.car());
3577      }
3578    };
3579
3580  // ### block
3581  private static final SpecialOperator BLOCK =
3582    new SpecialOperator(Symbol.BLOCK, "name &rest forms")
3583    {
3584      @Override
3585      public LispObject execute(LispObject args, Environment env)
3586        throws ConditionThrowable
3587      {
3588        if (args == NIL)
3589          return error(new WrongNumberOfArgumentsException(this));
3590        LispObject tag;
3591            tag = checkSymbol(args.car());
3592        LispObject body = ((Cons)args).cdr();
3593        Environment ext = new Environment(env);
3594        final LispObject block = new LispObject();
3595        ext.addBlock(tag, block);
3596        LispObject result = NIL;
3597        final LispThread thread = LispThread.currentThread();
3598        try
3599          {
3600            return progn(body, ext, thread);
3601          }
3602        catch (Return ret)
3603          {
3604            if (ret.getBlock() == block)
3605              {
3606                return ret.getResult();
3607              }
3608            throw ret;
3609          }
3610      }
3611    };
3612
3613  // ### return-from
3614  private static final SpecialOperator RETURN_FROM =
3615    new SpecialOperator(Symbol.RETURN_FROM, "name &optional value")
3616    {
3617      @Override
3618      public LispObject execute(LispObject args, Environment env)
3619        throws ConditionThrowable
3620      {
3621        final int length = args.length();
3622        if (length < 1 || length > 2)
3623          return error(new WrongNumberOfArgumentsException(this));
3624        Symbol symbol;
3625            symbol = checkSymbol(args.car());
3626
3627        LispObject block = env.lookupBlock(symbol);
3628        if (block == null)
3629          {
3630            FastStringBuffer sb = new FastStringBuffer("No block named ");
3631            sb.append(symbol.getName());
3632            sb.append(" is currently visible.");
3633            error(new LispError(sb.toString()));
3634          }
3635        LispObject result;
3636        if (length == 2)
3637          result = eval(args.cadr(), env, LispThread.currentThread());
3638        else
3639          result = NIL;
3640        throw new Return(symbol, block, result);
3641      }
3642    };
3643
3644  // ### catch
3645  private static final SpecialOperator CATCH =
3646    new SpecialOperator(Symbol.CATCH, "tag &body body")
3647    {
3648      @Override
3649      public LispObject execute(LispObject args, Environment env)
3650        throws ConditionThrowable
3651      {
3652        if (args.length() < 1)
3653          return error(new WrongNumberOfArgumentsException(this));
3654        final LispThread thread = LispThread.currentThread();
3655        LispObject tag = eval(args.car(), env, thread);
3656        thread.pushCatchTag(tag);
3657        LispObject body = args.cdr();
3658        LispObject result = NIL;
3659        try
3660          {
3661            return progn(body, env, thread);
3662          }
3663        catch (Throw t)
3664          {
3665            if (t.tag == tag)
3666              {
3667                return t.getResult(thread);
3668              }
3669            throw t;
3670          }
3671        catch (Return ret)
3672          {
3673            throw ret;
3674          }
3675        finally
3676          {
3677            thread.popCatchTag();
3678          }
3679      }
3680    };
3681
3682  // ### throw
3683  private static final SpecialOperator THROW =
3684    new SpecialOperator(Symbol.THROW, "tag result")
3685    {
3686      @Override
3687      public LispObject execute(LispObject args, Environment env)
3688        throws ConditionThrowable
3689      {
3690        if (args.length() != 2)
3691          return error(new WrongNumberOfArgumentsException(this));
3692        final LispThread thread = LispThread.currentThread();
3693        thread.throwToTag(eval(args.car(), env, thread),
3694                          eval(args.cadr(), env, thread));
3695        // Not reached.
3696        return NIL;
3697      }
3698    };
3699
3700  // ### unwind-protect
3701  private static final SpecialOperator UNWIND_PROTECT =
3702    new SpecialOperator(Symbol.UNWIND_PROTECT, "protected &body cleanup")
3703    {
3704      @Override
3705      public LispObject execute(LispObject args, Environment env)
3706        throws ConditionThrowable
3707      {
3708        final LispThread thread = LispThread.currentThread();
3709        LispObject result;
3710        LispObject[] values;
3711        try
3712          {
3713            result = eval(args.car(), env, thread);
3714          }
3715        finally
3716          {
3717            values = thread._values;
3718            LispObject body = args.cdr();
3719            while (body != NIL)
3720              {
3721                eval(body.car(), env, thread);
3722                body = ((Cons)body).cdr;
3723              }
3724            thread._values = values;
3725          }
3726        if (values != null)
3727          thread.setValues(values);
3728        else
3729          thread._values = null;
3730        return result;
3731      }
3732    };
3733
3734  // ### eval-when
3735  private static final SpecialOperator EVAL_WHEN =
3736    new SpecialOperator(Symbol.EVAL_WHEN, "situations &rest forms")
3737    {
3738      @Override
3739      public LispObject execute(LispObject args, Environment env)
3740        throws ConditionThrowable
3741      {
3742        LispObject situations = args.car();
3743        if (situations != NIL)
3744          {
3745            if (memq(Keyword.EXECUTE, situations) ||
3746                memq(Symbol.EVAL, situations))
3747              {
3748                return progn(args.cdr(), env, LispThread.currentThread());
3749              }
3750          }
3751        return NIL;
3752      }
3753    };
3754
3755  // ### multiple-value-bind
3756  // multiple-value-bind (var*) values-form declaration* form*
3757  // Should be a macro.
3758  private static final SpecialOperator MULTIPLE_VALUE_BIND =
3759    new SpecialOperator(Symbol.MULTIPLE_VALUE_BIND,
3760                        "vars value-form &body body")
3761    {
3762      @Override
3763      public LispObject execute(LispObject args, Environment env)
3764        throws ConditionThrowable
3765      {
3766        LispObject vars = args.car();
3767        args = args.cdr();
3768        LispObject valuesForm = args.car();
3769        LispObject body = args.cdr();
3770        final LispThread thread = LispThread.currentThread();
3771        LispObject value = eval(valuesForm, env, thread);
3772        LispObject[] values = thread._values;
3773        if (values == null)
3774          {
3775            // eval() did not return multiple values.
3776            values = new LispObject[1];
3777            values[0] = value;
3778          }
3779        // Process declarations.
3780        LispObject bodyAndDecls = parseBody(body, false);
3781        LispObject specials = parseSpecials(bodyAndDecls.NTH(1));
3782        body = bodyAndDecls.car();
3783
3784        final SpecialBinding lastSpecialBinding = thread.lastSpecialBinding;
3785        final Environment ext = new Environment(env);
3786        int i = 0;
3787        LispObject var = vars.car();
3788        while (var != NIL)
3789          {
3790            final Symbol sym;
3791
3792            sym =  checkSymbol(var);
3793
3794            LispObject val = i < values.length ? values[i] : NIL;
3795            if (specials != NIL && memq(sym, specials))
3796              {
3797                thread.bindSpecial(sym, val);
3798                ext.declareSpecial(sym);
3799              }
3800            else if (sym.isSpecialVariable())
3801              {
3802                thread.bindSpecial(sym, val);
3803              }
3804            else
3805              ext.bind(sym, val);
3806            vars = vars.cdr();
3807            var = vars.car();
3808            ++i;
3809          }
3810        // Make sure free special declarations are visible in the body.
3811        // "The scope of free declarations specifically does not include
3812        // initialization forms for bindings established by the form
3813        // containing the declarations." (3.3.4)
3814        while (specials != NIL)
3815          {
3816            Symbol symbol = (Symbol) specials.car();
3817            ext.declareSpecial(symbol);
3818            specials = ((Cons)specials).cdr;
3819          }
3820        thread._values = null;
3821        LispObject result = NIL;
3822        try
3823          {
3824            result  = progn(body, ext, thread);
3825          }
3826        finally
3827          {
3828            thread.lastSpecialBinding = lastSpecialBinding;
3829          }
3830        return result;
3831      }
3832    };
3833
3834  // ### multiple-value-prog1
3835  private static final SpecialOperator MULTIPLE_VALUE_PROG1 =
3836    new SpecialOperator(Symbol.MULTIPLE_VALUE_PROG1,
3837                        "values-form &rest forms")
3838    {
3839      @Override
3840      public LispObject execute(LispObject args, Environment env)
3841        throws ConditionThrowable
3842      {
3843        if (args.length() == 0)
3844          return error(new WrongNumberOfArgumentsException(this));
3845        final LispThread thread = LispThread.currentThread();
3846        LispObject result = eval(args.car(), env, thread);
3847        LispObject[] values = thread._values;
3848        while ((args = args.cdr()) != NIL)
3849          eval(args.car(), env, thread);
3850        if (values != null)
3851          thread.setValues(values);
3852        else
3853          thread._values = null;
3854        return result;
3855      }
3856    };
3857
3858  // ### multiple-value-call
3859  private static final SpecialOperator MULTIPLE_VALUE_CALL =
3860    new SpecialOperator(Symbol.MULTIPLE_VALUE_CALL, "fun &rest args")
3861    {
3862      @Override
3863      public LispObject execute(LispObject args, Environment env)
3864        throws ConditionThrowable
3865      {
3866        if (args.length() == 0)
3867          return error(new WrongNumberOfArgumentsException(this));
3868        final LispThread thread = LispThread.currentThread();
3869        LispObject function;
3870        LispObject obj = eval(args.car(), env, thread);
3871        args = args.cdr();
3872        if (obj instanceof Symbol)
3873          {
3874            function = obj.getSymbolFunction();
3875            if (function == null)
3876              error(new UndefinedFunction(obj));
3877          }
3878        else if (obj instanceof Function)
3879          {
3880            function = obj;
3881          }
3882        else
3883          {
3884            error(new LispError(obj.writeToString() +
3885                                 " is not a function name."));
3886            return NIL;
3887          }
3888        ArrayList<LispObject> arrayList = new ArrayList<LispObject>();
3889        while (args != NIL)
3890          {
3891            LispObject form = args.car();
3892            LispObject result = eval(form, env, thread);
3893            LispObject[] values = thread._values;
3894            if (values != null)
3895              {
3896                for (int i = 0; i < values.length; i++)
3897                  arrayList.add(values[i]);
3898              }
3899            else
3900              arrayList.add(result);
3901            args = ((Cons)args).cdr;
3902          }
3903        LispObject[] argv = new LispObject[arrayList.size()];
3904        arrayList.toArray(argv);
3905        return funcall(function, argv, thread);
3906      }
3907    };
3908
3909  // ### and
3910  // Should be a macro.
3911  private static final SpecialOperator AND =
3912    new SpecialOperator(Symbol.AND, "&rest forms")
3913    {
3914      @Override
3915      public LispObject execute(LispObject args, Environment env)
3916        throws ConditionThrowable
3917      {
3918        final LispThread thread = LispThread.currentThread();
3919        LispObject result = T;
3920        while (args != NIL)
3921          {
3922            result = eval(args.car(), env, thread);
3923            if (result == NIL)
3924              {
3925                if (((Cons)args).cdr != NIL)
3926                  {
3927                    // Not the last form.
3928                    thread._values = null;
3929                  }
3930                break;
3931              }
3932            args = ((Cons)args).cdr;
3933          }
3934        return result;
3935      }
3936    };
3937
3938  // ### or
3939  // Should be a macro.
3940  private static final SpecialOperator OR =
3941    new SpecialOperator(Symbol.OR, "&rest forms")
3942    {
3943      @Override
3944      public LispObject execute(LispObject args, Environment env)
3945        throws ConditionThrowable
3946      {
3947        final LispThread thread = LispThread.currentThread();
3948        LispObject result = NIL;
3949        while (args != NIL)
3950          {
3951            result = eval(args.car(), env, thread);
3952            if (result != NIL)
3953              {
3954                if (((Cons)args).cdr != NIL)
3955                  {
3956                    // Not the last form.
3957                    thread._values = null;
3958                  }
3959                break;
3960              }
3961            args = ((Cons)args).cdr;
3962          }
3963        return result;
3964      }
3965    };
3966
3967  // ### multiple-value-list form => list
3968  // Evaluates form and creates a list of the multiple values it returns.
3969  // Should be a macro.
3970  private static final SpecialOperator MULTIPLE_VALUE_LIST =
3971    new SpecialOperator(Symbol.MULTIPLE_VALUE_LIST, "value-form")
3972    {
3973      @Override
3974      public LispObject execute(LispObject args, Environment env)
3975        throws ConditionThrowable
3976      {
3977        if (args.length() != 1)
3978          return error(new WrongNumberOfArgumentsException(this));
3979        final LispThread thread = LispThread.currentThread();
3980        LispObject result = eval(((Cons)args).car, env, thread);
3981        LispObject[] values = thread._values;
3982        if (values == null)
3983          return new Cons(result);
3984        thread._values = null;
3985        LispObject list = NIL;
3986        for (int i = values.length; i-- > 0;)
3987          list = new Cons(values[i], list);
3988        return list;
3989      }
3990    };
3991
3992  // ### nth-value n form => object
3993  // Evaluates n and then form and returns the nth value returned by form, or
3994  // NIL if n >= number of values returned.
3995  // Should be a macro.
3996  private static final SpecialOperator NTH_VALUE =
3997    new SpecialOperator(Symbol.NTH_VALUE, "n form")
3998    {
3999      @Override
4000      public LispObject execute(LispObject args, Environment env)
4001        throws ConditionThrowable
4002      {
4003        if (args.length() != 2)
4004          return error(new WrongNumberOfArgumentsException(this));
4005        final LispThread thread = LispThread.currentThread();
4006        int n = Fixnum.getValue(eval(args.car(), env, thread));
4007        if (n < 0)
4008          n = 0;
4009        LispObject result = eval(args.cadr(), env, thread);
4010        LispObject[] values = thread._values;
4011        thread._values = null;
4012        if (values == null)
4013          {
4014            // A single value was returned.
4015            return n == 0 ? result : NIL;
4016          }
4017        if (n < values.length)
4018          return values[n];
4019        return NIL;
4020      }
4021    };
4022
4023  // ### call-count
4024  private static final Primitive CALL_COUNT =
4025    new Primitive("call-count", PACKAGE_SYS, true)
4026    {
4027      @Override
4028      public LispObject execute(LispObject arg) throws ConditionThrowable
4029      {
4030        return Fixnum.getInstance(arg.getCallCount());
4031      }
4032    };
4033
4034  // ### set-call-count
4035  private static final Primitive SET_CALL_COUNT =
4036    new Primitive("set-call-count", PACKAGE_SYS, true)
4037    {
4038      @Override
4039      public LispObject execute(LispObject first, LispObject second)
4040        throws ConditionThrowable
4041      {
4042        first.setCallCount(Fixnum.getValue(second));
4043        return second;
4044      }
4045    };
4046
4047  // ### call-count
4048  private static final Primitive HOT_COUNT =
4049    new Primitive("hot-count", PACKAGE_SYS, true)
4050    {
4051      @Override
4052      public LispObject execute(LispObject arg) throws ConditionThrowable
4053      {
4054        return Fixnum.getInstance(arg.getHotCount());
4055      }
4056    };
4057
4058  // ### set-call-count
4059  private static final Primitive SET_HOT_COUNT =
4060    new Primitive("set-hot-count", PACKAGE_SYS, true)
4061    {
4062      @Override
4063      public LispObject execute(LispObject first, LispObject second)
4064        throws ConditionThrowable
4065      {
4066        first.setHotCount(Fixnum.getValue(second));
4067        return second;
4068      }
4069    };
4070
4071    // ### lambda-name
4072  private static final Primitive LAMBDA_NAME =
4073    new Primitive("lambda-name", PACKAGE_SYS, true)
4074    {
4075      @Override
4076      public LispObject execute(LispObject arg) throws ConditionThrowable
4077      {
4078        if (arg instanceof Operator)
4079          {
4080            return ((Operator)arg).getLambdaName();
4081          }
4082        if (arg instanceof StandardGenericFunction)
4083          {
4084            return ((StandardGenericFunction)arg).getGenericFunctionName();
4085          }
4086        return type_error(arg, Symbol.FUNCTION);
4087      }
4088    };
4089
4090  // ### %set-lambda-name
4091  private static final Primitive _SET_LAMBDA_NAME =
4092    new Primitive("%set-lambda-name", PACKAGE_SYS, false)
4093    {
4094      @Override
4095      public LispObject execute(LispObject first, LispObject second)
4096        throws ConditionThrowable
4097      {
4098        if (first instanceof Operator)
4099          {
4100            ((Operator)first).setLambdaName(second);
4101            return second;
4102          }
4103        if (first instanceof StandardGenericFunction)
4104          {
4105            ((StandardGenericFunction)first).setGenericFunctionName(second);
4106            return second;
4107          }
4108        return type_error(first, Symbol.FUNCTION);
4109      }
4110    };
4111
4112  // ### shrink-vector vector new-size => vector
4113  // Destructively alters the vector, changing its length to NEW-SIZE, which
4114  // must be less than or equal to its current length.
4115  // shrink-vector vector new-size => vector
4116  private static final Primitive SHRINK_VECTOR =
4117    new Primitive("shrink-vector", PACKAGE_SYS, true, "vector new-size")
4118    {
4119      @Override
4120      public LispObject execute(LispObject first, LispObject second)
4121        throws ConditionThrowable
4122      {
4123        checkVector(first).shrink(Fixnum.getValue(second));
4124        return first;
4125      }
4126    };
4127
4128  // ### subseq sequence start &optional end
4129  private static final Primitive SUBSEQ =
4130    new Primitive(Symbol.SUBSEQ, "sequence start &optional end")
4131    {
4132      @Override
4133      public LispObject execute(LispObject first, LispObject second)
4134        throws ConditionThrowable
4135      {
4136        final int start = Fixnum.getValue(second);
4137        if (start < 0)
4138          {
4139            FastStringBuffer sb = new FastStringBuffer("Bad start index (");
4140            sb.append(start);
4141            sb.append(") for SUBSEQ.");
4142            error(new TypeError(sb.toString()));
4143          }
4144        if (first.listp())
4145          return list_subseq(first, start, -1);
4146        if (first instanceof AbstractVector)
4147          {
4148            final AbstractVector v = (AbstractVector) first;
4149            return v.subseq(start, v.length());
4150          }
4151        return type_error(first, Symbol.SEQUENCE);
4152      }
4153      @Override
4154      public LispObject execute(LispObject first, LispObject second,
4155                                LispObject third)
4156        throws ConditionThrowable
4157      {
4158        final int start = Fixnum.getValue(second);
4159        if (start < 0)
4160          {
4161            FastStringBuffer sb = new FastStringBuffer("Bad start index (");
4162            sb.append(start);
4163            sb.append(").");
4164            error(new TypeError(sb.toString()));
4165          }
4166        int end;
4167        if (third != NIL)
4168          {
4169            end = Fixnum.getValue(third);
4170            if (start > end)
4171              {
4172                FastStringBuffer sb = new FastStringBuffer("Start index (");
4173                sb.append(start);
4174                sb.append(") is greater than end index (");
4175                sb.append(end);
4176                sb.append(") for SUBSEQ.");
4177                error(new TypeError(sb.toString()));
4178              }
4179          }
4180        else
4181          end = -1;
4182        if (first.listp())
4183          return list_subseq(first, start, end);
4184        if (first instanceof AbstractVector)
4185          {
4186            final AbstractVector v = (AbstractVector) first;
4187            if (end < 0)
4188              end = v.length();
4189            return v.subseq(start, end);
4190          }
4191        return type_error(first, Symbol.SEQUENCE);
4192      }
4193    };
4194
4195  private static final LispObject list_subseq(LispObject list, int start,
4196                                              int end)
4197    throws ConditionThrowable
4198  {
4199    int index = 0;
4200    LispObject result = NIL;
4201    while (list != NIL)
4202      {
4203        if (end >= 0 && index == end)
4204          return result.nreverse();
4205        if (index++ >= start)
4206          result = new Cons(list.car(), result);
4207        list = list.cdr();
4208      }
4209    return result.nreverse();
4210  }
4211
4212  // ### list
4213  private static final Primitive LIST =
4214    new Primitive(Symbol.LIST, "&rest objects")
4215    {
4216      @Override
4217      public LispObject execute()
4218      {
4219        return NIL;
4220      }
4221      @Override
4222      public LispObject execute(LispObject arg)
4223      {
4224        return new Cons(arg);
4225      }
4226      @Override
4227      public LispObject execute(LispObject first, LispObject second)
4228      {
4229        return new Cons(first, new Cons(second));
4230      }
4231      @Override
4232      public LispObject execute(LispObject first, LispObject second,
4233                                LispObject third)
4234      {
4235        return new Cons(first, new Cons(second, new Cons(third)));
4236      }
4237      @Override
4238      public LispObject execute(LispObject first, LispObject second,
4239                                LispObject third, LispObject fourth)
4240      {
4241        return new Cons(first,
4242                        new Cons(second,
4243                                 new Cons(third,
4244                                          new Cons(fourth))));
4245      }
4246      @Override
4247      public LispObject execute(LispObject[] args) throws ConditionThrowable
4248      {
4249        LispObject result = NIL;
4250        for (int i = args.length; i-- > 0;)
4251          result = new Cons(args[i], result);
4252        return result;
4253      }
4254    };
4255
4256  // ### list*
4257  private static final Primitive LIST_STAR =
4258    new Primitive(Symbol.LIST_STAR, "&rest objects")
4259    {
4260      @Override
4261      public LispObject execute() throws ConditionThrowable
4262      {
4263        return error(new WrongNumberOfArgumentsException(this));
4264      }
4265      @Override
4266      public LispObject execute(LispObject arg) throws ConditionThrowable
4267      {
4268        return arg;
4269      }
4270      @Override
4271      public LispObject execute(LispObject first, LispObject second)
4272        throws ConditionThrowable
4273      {
4274        return new Cons(first, second);
4275      }
4276      @Override
4277      public LispObject execute(LispObject first, LispObject second,
4278                                LispObject third)
4279        throws ConditionThrowable
4280      {
4281        return new Cons(first, new Cons(second, third));
4282      }
4283      @Override
4284      public LispObject execute(LispObject first, LispObject second,
4285                                LispObject third, LispObject fourth)
4286        throws ConditionThrowable
4287      {
4288        return new Cons(first,
4289                        new Cons(second,
4290                                 new Cons(third, fourth)));
4291      }
4292      @Override
4293      public LispObject execute(LispObject[] args) throws ConditionThrowable
4294      {
4295        int i = args.length - 1;
4296        LispObject result = args[i];
4297        while (i-- > 0)
4298          result = new Cons(args[i], result);
4299        return result;
4300      }
4301    };
4302
4303  // ### nreverse
4304  public static final Primitive NREVERSE =
4305    new Primitive(Symbol.NREVERSE, "sequence")
4306    {
4307      @Override
4308      public LispObject execute (LispObject arg) throws ConditionThrowable
4309      {
4310        return arg.nreverse();
4311      }
4312    };
4313
4314  // ### nreconc
4315  private static final Primitive NRECONC =
4316    new Primitive(Symbol.NRECONC, "list tail")
4317    {
4318      @Override
4319      public LispObject execute(LispObject list, LispObject obj)
4320        throws ConditionThrowable
4321      {
4322        if (list instanceof Cons)
4323          {
4324            LispObject list3 = list.cdr();
4325            if (list3 instanceof Cons)
4326              {
4327                if (list3.cdr() instanceof Cons)
4328                  {
4329                    LispObject list1 = list3;
4330                    LispObject list2 = NIL;
4331                    do
4332                      {
4333                        LispObject h = list3.cdr();
4334                        list3.setCdr(list2);
4335                        list2 = list3;
4336                        list3 = h;
4337                      } while (list3.cdr() instanceof Cons);
4338                    list.setCdr(list2);
4339                    list1.setCdr(list3);
4340                  }
4341                LispObject h = list.car();
4342                list.setCar(list3.car());
4343                list3.setCar(h);
4344                list3.setCdr(obj);
4345              }
4346            else if (list3 == NIL)
4347              {
4348                list.setCdr(obj);
4349              }
4350            else
4351              type_error(list3, Symbol.LIST);
4352            return list;
4353          }
4354        else if (list == NIL)
4355          return obj;
4356        else
4357          return type_error(list, Symbol.LIST);
4358      }
4359    };
4360
4361  // ### reverse
4362  private static final Primitive REVERSE =
4363    new Primitive(Symbol.REVERSE, "sequence")
4364    {
4365      @Override
4366      public LispObject execute(LispObject arg) throws ConditionThrowable
4367      {
4368        return arg.reverse();
4369      }
4370    };
4371
4372  // ### delete-eq item sequence => result-sequence
4373  private static final Primitive DELETE_EQ =
4374    new Primitive("delete-eq", PACKAGE_SYS, true, "item sequence")
4375    {
4376      @Override
4377      public LispObject execute(LispObject item, LispObject sequence)
4378        throws ConditionThrowable
4379      {
4380        if (sequence instanceof AbstractVector)
4381          return ((AbstractVector)sequence).deleteEq(item);
4382        else
4383          return LIST_DELETE_EQ.execute(item, sequence);
4384      }
4385    };
4386
4387  // ### delete-eql item seqluence => result-seqluence
4388  private static final Primitive DELETE_EQL =
4389    new Primitive("delete-eql", PACKAGE_SYS, true, "item sequence")
4390    {
4391      @Override
4392      public LispObject execute(LispObject item, LispObject sequence)
4393        throws ConditionThrowable
4394      {
4395        if (sequence instanceof AbstractVector)
4396          return ((AbstractVector)sequence).deleteEql(item);
4397        else
4398          return LIST_DELETE_EQL.execute(item, sequence);
4399      }
4400    };
4401
4402  // ### list-delete-eq item list => result-list
4403  private static final Primitive LIST_DELETE_EQ =
4404    new Primitive("list-delete-eq", PACKAGE_SYS, true, "item list")
4405    {
4406      @Override
4407      public LispObject execute(LispObject item, LispObject list)
4408        throws ConditionThrowable
4409      {
4410        if (list instanceof Cons)
4411          {
4412            LispObject tail = list;
4413            LispObject splice = list;
4414            while (tail instanceof Cons)
4415              {
4416                LispObject car = tail.car();
4417                if (car == item)
4418                  {
4419                    if (tail.cdr() != NIL)
4420                      {
4421                        LispObject temp = tail;
4422                        tail.setCar(temp.cadr());
4423                        tail.setCdr(temp.cddr());
4424                      }
4425                    else
4426                      {
4427                        // Last item.
4428                        if (tail == list)
4429                          return NIL;
4430                        splice.setCdr(NIL);
4431                        return list;
4432                      }
4433                  }
4434                else
4435                  {
4436                    splice = tail;
4437                    tail = tail.cdr();
4438                  }
4439              }
4440            if (tail == NIL)
4441              return list;
4442            else
4443              return type_error(tail, Symbol.LIST);
4444          }
4445        else if (list == NIL)
4446          return list;
4447        else
4448          return type_error(list, Symbol.LIST);
4449      }
4450    };
4451
4452  // ### list-delete-eql item list => result-list
4453  private static final Primitive LIST_DELETE_EQL =
4454    new Primitive("list-delete-eql", PACKAGE_SYS, true, "item list")
4455    {
4456      @Override
4457      public LispObject execute(LispObject item, LispObject list)
4458        throws ConditionThrowable
4459      {
4460        if (list instanceof Cons)
4461          {
4462            LispObject tail = list;
4463            LispObject splice = list;
4464            while (tail instanceof Cons)
4465              {
4466                LispObject car = tail.car();
4467                if (car.eql(item))
4468                  {
4469                    if (tail.cdr() != NIL)
4470                      {
4471                        LispObject temp = tail;
4472                        tail.setCar(temp.cadr());
4473                        tail.setCdr(temp.cddr());
4474                      }
4475                    else
4476                      {
4477                        // Last item.
4478                        if (tail == list)
4479                          return NIL;
4480                        splice.setCdr(NIL);
4481                        return list;
4482                      }
4483                  }
4484                else
4485                  {
4486                    splice = tail;
4487                    tail = tail.cdr();
4488                  }
4489              }
4490            if (tail == NIL)
4491              return list;
4492            else
4493              return type_error(tail, Symbol.LIST);
4494          }
4495        else if (list == NIL)
4496          return list;
4497        else
4498          return type_error(list, Symbol.LIST);
4499      }
4500    };
4501
4502  // ### vector-delete-eq item vector => result-vector
4503  private static final Primitive VECTOR_DELETE_EQ =
4504    new Primitive("vector-delete-eq", PACKAGE_SYS, true, "item vector")
4505    {
4506      @Override
4507      public LispObject execute(LispObject item, LispObject vector)
4508        throws ConditionThrowable
4509      {
4510          checkVector(vector).deleteEq(item);
4511          return vector;
4512      }
4513    };
4514
4515  // ### vector-delete-eql item vector => result-vector
4516  private static final Primitive VECTOR_DELETE_EQL =
4517    new Primitive("vector-delete-eql", PACKAGE_SYS, true, "item vector")
4518    {
4519      @Override
4520      public LispObject execute(LispObject item, LispObject vector)
4521        throws ConditionThrowable
4522      {
4523          checkVector(vector).deleteEql(item);
4524          return vector;
4525      }
4526    };
4527
4528  // ### %set-elt
4529  // %setelt sequence index newval => newval
4530  private static final Primitive _SET_ELT =
4531    new Primitive("%set-elt", PACKAGE_SYS, false)
4532    {
4533      @Override
4534      public LispObject execute(LispObject first, LispObject second,
4535                                LispObject third)
4536        throws ConditionThrowable
4537      {
4538        if (first instanceof AbstractVector)
4539          {
4540            ((AbstractVector)first).aset(Fixnum.getValue(second), third);
4541            return third;
4542          }
4543        if (first instanceof Cons)
4544          {
4545            int index = Fixnum.getValue(second);
4546            if (index < 0)
4547              error(new TypeError());
4548            LispObject list = first;
4549            int i = 0;
4550            while (true)
4551              {
4552                if (i == index)
4553                  {
4554                    list.setCar(third);
4555                    return third;
4556                  }
4557                list = list.cdr();
4558                if (list == NIL)
4559                  error(new TypeError());
4560                ++i;
4561              }
4562          }
4563        return type_error(first, Symbol.SEQUENCE);
4564      }
4565    };
4566
4567  // ### %make-list
4568  private static final Primitive _MAKE_LIST =
4569    new Primitive("%make-list", PACKAGE_SYS, true)
4570    {
4571      @Override
4572      public LispObject execute(LispObject first, LispObject second)
4573        throws ConditionThrowable
4574      {
4575        int size = Fixnum.getValue(first);
4576        if (size < 0)
4577          return type_error(first, list(Symbol.INTEGER, Fixnum.ZERO,
4578                                              Symbol.MOST_POSITIVE_FIXNUM.getSymbolValue()));
4579        LispObject result = NIL;
4580        for (int i = size; i-- > 0;)
4581          result = new Cons(second, result);
4582        return result;
4583      }
4584    };
4585
4586  // ### %member item list key test test-not => tail
4587  private static final Primitive _MEMBER =
4588    new Primitive("%member", PACKAGE_SYS, true)
4589    {
4590      @Override
4591      public LispObject execute(LispObject item, LispObject list,
4592                                LispObject key, LispObject test,
4593                                LispObject testNot)
4594        throws ConditionThrowable
4595      {
4596        LispObject tail = checkList(list);
4597        if (test != NIL && testNot != NIL)
4598          error(new LispError("MEMBER: test and test-not both supplied"));
4599        if (testNot == NIL)
4600          {
4601            if (test == NIL || test == Symbol.EQL)
4602              test = EQL;
4603          }
4604        if (key == NIL)
4605          {
4606            if (test == EQL)
4607              {
4608                while (tail instanceof Cons)
4609                  {
4610                    if (item.eql(((Cons)tail).car))
4611                      return tail;
4612                    tail = ((Cons)tail).cdr;
4613                  }
4614              }
4615            else if (test != NIL)
4616              {
4617                while (tail instanceof Cons)
4618                  {
4619                    LispObject candidate = ((Cons)tail).car;
4620                    if (test.execute(item, candidate) != NIL)
4621                      return tail;
4622                    tail = ((Cons)tail).cdr;
4623                  }
4624              }
4625            else
4626              {
4627                // test == NIL
4628                while (tail instanceof Cons)
4629                  {
4630                    LispObject candidate = ((Cons)tail).car;
4631                    if (testNot.execute(item, candidate) == NIL)
4632                      return tail;
4633                    tail = ((Cons)tail).cdr;
4634                  }
4635              }
4636          }
4637        else
4638          {
4639            // key != NIL
4640            while (tail instanceof Cons)
4641              {
4642                LispObject candidate = key.execute(((Cons)tail).car);
4643                if (test != NIL)
4644                  {
4645                    if (test.execute(item, candidate) != NIL)
4646                      return tail;
4647                  }
4648                else
4649                  {
4650                    if (testNot.execute(item, candidate) == NIL)
4651                      return tail;
4652                  }
4653                tail = ((Cons)tail).cdr;
4654              }
4655          }
4656        if (tail != NIL)
4657          type_error(tail, Symbol.LIST);
4658        return NIL;
4659      }
4660    };
4661
4662  // ### funcall-key function-or-nil element
4663  private static final Primitive FUNCALL_KEY =
4664    new Primitive("funcall-key", PACKAGE_SYS, false)
4665    {
4666      @Override
4667      public LispObject execute(LispObject first, LispObject second)
4668        throws ConditionThrowable
4669      {
4670        if (first != NIL)
4671          return LispThread.currentThread().execute(first, second);
4672        return second;
4673      }
4674    };
4675
4676  // ### coerce-to-function
4677  private static final Primitive COERCE_TO_FUNCTION =
4678    new Primitive("coerce-to-function", PACKAGE_SYS, true)
4679    {
4680      @Override
4681      public LispObject execute(LispObject arg) throws ConditionThrowable
4682      {
4683        return coerceToFunction(arg);
4684      }
4685    };
4686
4687  // ### make-closure lambda-form environment => closure
4688  private static final Primitive MAKE_CLOSURE =
4689    new Primitive("make-closure", PACKAGE_SYS, true)
4690    {
4691      @Override
4692      public LispObject execute(LispObject first, LispObject second)
4693        throws ConditionThrowable
4694      {
4695        if (first instanceof Cons && ((Cons)first).car == Symbol.LAMBDA)
4696          {
4697            final Environment env;
4698            if (second == NIL)
4699              env = new Environment();
4700            else
4701              env = checkEnvironment(second);
4702            return new Closure(first, env);
4703          }
4704        return error(new TypeError("The argument to MAKE-CLOSURE is not a lambda form."));
4705      }
4706    };
4707
4708  // ### streamp
4709  private static final Primitive STREAMP =
4710    new Primitive(Symbol.STREAMP, "object")
4711    {
4712      @Override
4713      public LispObject execute(LispObject arg)
4714      {
4715        return arg instanceof Stream ? T : NIL;
4716      }
4717    };
4718
4719  // ### integerp
4720  private static final Primitive INTEGERP =
4721    new Primitive(Symbol.INTEGERP, "object")
4722    {
4723      @Override
4724      public LispObject execute(LispObject arg)
4725      {
4726        return arg.INTEGERP();
4727      }
4728    };
4729
4730  // ### evenp
4731  private static final Primitive EVENP =
4732    new Primitive(Symbol.EVENP, "integer")
4733    {
4734      @Override
4735      public LispObject execute(LispObject arg) throws ConditionThrowable
4736      {
4737        return arg.EVENP();
4738      }
4739    };
4740
4741  // ### oddp
4742  private static final Primitive ODDP = new Primitive(Symbol.ODDP, "integer")
4743    {
4744      @Override
4745      public LispObject execute(LispObject arg) throws ConditionThrowable
4746      {
4747        return arg.ODDP();
4748      }
4749    };
4750
4751  // ### numberp
4752  private static final Primitive NUMBERP =
4753    new Primitive(Symbol.NUMBERP, "object")
4754    {
4755      @Override
4756      public LispObject execute(LispObject arg)
4757      {
4758        return arg.NUMBERP();
4759      }
4760    };
4761
4762  // ### realp
4763  private static final Primitive REALP =
4764    new Primitive(Symbol.REALP, "object")
4765    {
4766      @Override
4767      public LispObject execute(LispObject arg)
4768      {
4769        return arg.REALP();
4770      }
4771    };
4772
4773  // ### rationalp
4774  private static final Primitive RATIONALP =
4775    new Primitive(Symbol.RATIONALP,"object")
4776    {
4777      @Override
4778      public LispObject execute(LispObject arg)
4779      {
4780        return arg.RATIONALP();
4781      }
4782    };
4783
4784  // ### complex
4785  private static final Primitive COMPLEX =
4786    new Primitive(Symbol.COMPLEX, "realpart &optional imagpart")
4787    {
4788      @Override
4789      public LispObject execute(LispObject arg) throws ConditionThrowable
4790      {
4791        if (arg instanceof SingleFloat)
4792          return Complex.getInstance(arg, SingleFloat.ZERO);
4793        if (arg instanceof DoubleFloat)
4794          return Complex.getInstance(arg, DoubleFloat.ZERO);
4795        if (arg.realp())
4796          return arg;
4797        return type_error(arg, Symbol.REAL);
4798      }
4799      @Override
4800      public LispObject execute(LispObject first, LispObject second)
4801        throws ConditionThrowable
4802      {
4803        return Complex.getInstance(first, second);
4804      }
4805    };
4806
4807  // ### complexp
4808  private static final Primitive COMPLEXP =
4809    new Primitive(Symbol.COMPLEXP, "object")
4810    {
4811      @Override
4812      public LispObject execute(LispObject arg)
4813      {
4814        return arg.COMPLEXP();
4815      }
4816    };
4817
4818  // ### numerator
4819  private static final Primitive NUMERATOR =
4820    new Primitive(Symbol.NUMERATOR, "rational")
4821    {
4822      @Override
4823      public LispObject execute(LispObject arg) throws ConditionThrowable
4824      {
4825        return arg.NUMERATOR();
4826      }
4827    };
4828
4829  // ### denominator
4830  private static final Primitive DENOMINATOR =
4831    new Primitive(Symbol.DENOMINATOR, "rational")
4832    {
4833      @Override
4834      public LispObject execute(LispObject arg) throws ConditionThrowable
4835      {
4836        return arg.DENOMINATOR();
4837      }
4838    };
4839
4840  // ### realpart
4841  private static final Primitive REALPART =
4842    new Primitive(Symbol.REALPART, "number")
4843    {
4844      @Override
4845      public LispObject execute(LispObject arg) throws ConditionThrowable
4846      {
4847        if (arg instanceof Complex)
4848          return ((Complex)arg).getRealPart();
4849        if (arg.numberp())
4850          return arg;
4851        return type_error(arg, Symbol.NUMBER);
4852      }
4853    };
4854
4855  // ### imagpart
4856  private static final Primitive IMAGPART =
4857    new Primitive(Symbol.IMAGPART, "number")
4858    {
4859      @Override
4860      public LispObject execute(LispObject arg) throws ConditionThrowable
4861      {
4862        if (arg instanceof Complex)
4863          return ((Complex)arg).getImaginaryPart();
4864        return arg.multiplyBy(Fixnum.ZERO);
4865      }
4866    };
4867
4868  // ### integer-length
4869  private static final Primitive INTEGER_LENGTH =
4870    new Primitive(Symbol.INTEGER_LENGTH, "integer")
4871    {
4872      @Override
4873      public LispObject execute(LispObject arg) throws ConditionThrowable
4874      {
4875        if (arg instanceof Fixnum)
4876          {
4877            int n = ((Fixnum)arg).value;
4878            if (n < 0)
4879              n = ~n;
4880            int count = 0;
4881            while (n > 0)
4882              {
4883                n = n >>> 1;
4884                ++count;
4885              }
4886            return Fixnum.getInstance(count);
4887          }
4888        if (arg instanceof Bignum)
4889          return Fixnum.getInstance(((Bignum)arg).value.bitLength());
4890        return type_error(arg, Symbol.INTEGER);
4891      }
4892    };
4893
4894  // ### gcd-2
4895  private static final Primitive GCD_2 =
4896    new Primitive("gcd-2", PACKAGE_SYS, false)
4897    {
4898      @Override
4899      public LispObject execute(LispObject first, LispObject second)
4900        throws ConditionThrowable
4901      {
4902        BigInteger n1, n2;
4903        if (first instanceof Fixnum)
4904          n1 = BigInteger.valueOf(((Fixnum)first).value);
4905        else if (first instanceof Bignum)
4906          n1 = ((Bignum)first).value;
4907        else
4908          return type_error(first, Symbol.INTEGER);
4909        if (second instanceof Fixnum)
4910          n2 = BigInteger.valueOf(((Fixnum)second).value);
4911        else if (second instanceof Bignum)
4912          n2 = ((Bignum)second).value;
4913        else
4914          return type_error(second, Symbol.INTEGER);
4915        return number(n1.gcd(n2));
4916      }
4917    };
4918
4919  // ### identity-hash-code
4920  private static final Primitive IDENTITY_HASH_CODE =
4921    new Primitive("identity-hash-code", PACKAGE_SYS, true)
4922    {
4923      @Override
4924      public LispObject execute(LispObject arg) throws ConditionThrowable
4925      {
4926        return Fixnum.getInstance(System.identityHashCode(arg));
4927      }
4928    };
4929
4930  // ### simple-vector-search pattern vector => position
4931  // Searches vector for pattern.
4932  private static final Primitive SIMPLE_VECTOR_SEARCH =
4933    new Primitive("simple-vector-search", PACKAGE_SYS, false)
4934    {
4935      @Override
4936      public LispObject execute(LispObject first, LispObject second)
4937        throws ConditionThrowable
4938      {
4939        AbstractVector v = checkVector(second);
4940        if (first.length() == 0)
4941          return Fixnum.ZERO;
4942        final int patternLength = first.length();
4943        final int limit = v.length() - patternLength;
4944        if (first instanceof AbstractVector)
4945          {
4946            AbstractVector pattern = (AbstractVector) first;
4947            LispObject element = pattern.AREF(0);
4948            for (int i = 0; i <= limit; i++)
4949              {
4950                if (v.AREF(i).eql(element))
4951                  {
4952                    // Found match for first element of pattern.
4953                    boolean match = true;
4954                    // We've already checked the first element.
4955                    int j = i + 1;
4956                    for (int k = 1; k < patternLength; k++)
4957                      {
4958                        if (v.AREF(j).eql(pattern.AREF(k)))
4959                          {
4960                            ++j;
4961                          }
4962                        else
4963                          {
4964                            match = false;
4965                            break;
4966                          }
4967                      }
4968                    if (match)
4969                      return Fixnum.getInstance(i);
4970                  }
4971              }
4972          }
4973        else
4974          {
4975            // Pattern is a list.
4976            LispObject element = first.car();
4977            for (int i = 0; i <= limit; i++)
4978              {
4979                if (v.AREF(i).eql(element))
4980                  {
4981                    // Found match for first element of pattern.
4982                    boolean match = true;
4983                    // We've already checked the first element.
4984                    int j = i + 1;
4985                    for (LispObject rest = first.cdr(); rest != NIL; rest = rest.cdr())
4986                      {
4987                        if (v.AREF(j).eql(rest.car()))
4988                          {
4989                            ++j;
4990                          }
4991                        else
4992                          {
4993                            match = false;
4994                            break;
4995                          }
4996                      }
4997                    if (match)
4998                      return Fixnum.getInstance(i);
4999                  }
5000              }
5001          }
5002        return NIL;
5003      }
5004    };
5005
5006  // ### uptime
5007  private static final Primitive UPTIME =
5008    new Primitive("uptime", PACKAGE_EXT, true)
5009    {
5010      @Override
5011      public LispObject execute() throws ConditionThrowable
5012      {
5013        return number(System.currentTimeMillis() - Main.startTimeMillis);
5014      }
5015    };
5016
5017  // ### built-in-function-p
5018  private static final Primitive BUILT_IN_FUNCTION_P =
5019    new Primitive("built-in-function-p", PACKAGE_SYS, true)
5020    {
5021      @Override
5022      public LispObject execute(LispObject arg) throws ConditionThrowable
5023      {
5024            return checkSymbol(arg).isBuiltInFunction() ? T : NIL;
5025      }
5026    };
5027
5028  // ### inspected-parts
5029  private static final Primitive INSPECTED_PARTS =
5030    new Primitive("inspected-parts", PACKAGE_SYS, true)
5031    {
5032      @Override
5033      public LispObject execute(LispObject arg) throws ConditionThrowable
5034      {
5035        return arg.getParts();
5036      }
5037    };
5038
5039  // ### inspected-description
5040  private static final Primitive INSPECTED_DESCRIPTION =
5041    new Primitive("inspected-description", PACKAGE_SYS, false)
5042    {
5043      @Override
5044      public LispObject execute(LispObject arg) throws ConditionThrowable
5045      {
5046        return arg.getDescription();
5047      }
5048    };
5049
5050  // ### symbol-name
5051  public static final Primitive SYMBOL_NAME =
5052    new Primitive(Symbol.SYMBOL_NAME, "symbol")
5053    {
5054      @Override
5055      public LispObject execute(LispObject arg) throws ConditionThrowable
5056      {
5057          return checkSymbol(arg).name;
5058      }
5059    };
5060
5061  // ### symbol-package
5062  public static final Primitive SYMBOL_PACKAGE =
5063    new Primitive(Symbol.SYMBOL_PACKAGE, "symbol")
5064    {
5065      @Override
5066      public LispObject execute(LispObject arg) throws ConditionThrowable
5067      {
5068          return checkSymbol(arg).getPackage();
5069      }
5070    };
5071
5072  // ### symbol-function
5073  public static final Primitive SYMBOL_FUNCTION =
5074    new Primitive(Symbol.SYMBOL_FUNCTION, "symbol")
5075    {
5076      @Override
5077      public LispObject execute(LispObject arg) throws ConditionThrowable
5078      {
5079            LispObject function = checkSymbol(arg).getSymbolFunction();
5080            if (function != null)
5081              return function;
5082            return error(new UndefinedFunction(arg));
5083
5084      }
5085    };
5086
5087  // ### %set-symbol-function
5088  public static final Primitive _SET_SYMBOL_FUNCTION =
5089    new Primitive("%set-symbol-function", PACKAGE_SYS, false, "symbol function")
5090    {
5091      @Override
5092      public LispObject execute(LispObject first, LispObject second)
5093        throws ConditionThrowable
5094      {
5095            checkSymbol(first).setSymbolFunction(second);
5096            return second;
5097      }
5098    };
5099
5100  // ### symbol-plist
5101  public static final Primitive SYMBOL_PLIST =
5102    new Primitive(Symbol.SYMBOL_PLIST, "symbol")
5103    {
5104      @Override
5105      public LispObject execute(LispObject arg) throws ConditionThrowable
5106      {
5107            return checkSymbol(arg).getPropertyList();
5108      }
5109    };
5110
5111  // ### keywordp
5112  public static final Primitive KEYWORDP =
5113    new Primitive(Symbol.KEYWORDP, "object")
5114    {
5115      @Override
5116      public LispObject execute(LispObject arg) throws ConditionThrowable
5117      {
5118        if (arg instanceof Symbol)
5119          {
5120            if (checkSymbol(arg).getPackage() == PACKAGE_KEYWORD)
5121              return T;
5122          }
5123        return NIL;
5124      }
5125    };
5126
5127  // ### make-symbol
5128  public static final Primitive MAKE_SYMBOL =
5129    new Primitive(Symbol.MAKE_SYMBOL, "name")
5130    {
5131      @Override
5132      public LispObject execute(LispObject arg) throws ConditionThrowable
5133      {
5134        if (arg instanceof SimpleString)
5135          return new Symbol((SimpleString)arg);
5136        // Not a simple string.
5137        if (arg instanceof AbstractString)
5138          return new Symbol(arg.getStringValue());
5139        return type_error(arg, Symbol.STRING);
5140      }
5141    };
5142
5143  // ### makunbound
5144  public static final Primitive MAKUNBOUND =
5145    new Primitive(Symbol.MAKUNBOUND, "symbol")
5146    {
5147      @Override
5148      public LispObject execute(LispObject arg) throws ConditionThrowable
5149      {
5150            checkSymbol(arg).setSymbolValue(null);
5151            return arg;
5152      }
5153    };
5154
5155  // ### %class-name
5156  private static final Primitive _CLASS_NAME =
5157    new Primitive("%class-name", PACKAGE_SYS, true, "class")
5158    {
5159      @Override
5160      public LispObject execute(LispObject arg) throws ConditionThrowable
5161      {
5162          return checkClass(arg).symbol;
5163      }
5164    };
5165
5166  // ### %set-class-name
5167  private static final Primitive _SET_CLASS_NAME =
5168    new Primitive("%set-class-name", PACKAGE_SYS, true)
5169    {
5170      @Override
5171      public LispObject execute(LispObject first, LispObject second)
5172        throws ConditionThrowable
5173      {
5174          checkClass(first).symbol = checkSymbol(second);
5175          return second;
5176      }
5177    };
5178
5179  // ### class-layout
5180  private static final Primitive CLASS_LAYOUT =
5181    new Primitive("class-layout", PACKAGE_SYS, true, "class")
5182    {
5183      @Override
5184      public LispObject execute(LispObject arg) throws ConditionThrowable
5185      {
5186          Layout layout = checkClass(arg).getClassLayout();
5187          return layout != null ? layout : NIL;
5188      }
5189    };
5190
5191  // ### %set-class-layout
5192  private static final Primitive _SET_CLASS_LAYOUT =
5193    new Primitive("%set-class-layout", PACKAGE_SYS, true, "class layout")
5194    {
5195      @Override
5196      public LispObject execute(LispObject first, LispObject second)
5197        throws ConditionThrowable
5198      {
5199        if (second instanceof Layout)
5200          {
5201            checkClass(first).setClassLayout((Layout)second);
5202            return second;
5203          }
5204        return type_error(second, Symbol.LAYOUT);
5205      }
5206    };
5207
5208  // ### class-direct-superclasses
5209  private static final Primitive CLASS_DIRECT_SUPERCLASSES =
5210    new Primitive("class-direct-superclasses", PACKAGE_SYS, true)
5211    {
5212      @Override
5213      public LispObject execute(LispObject arg) throws ConditionThrowable
5214      {
5215            return checkClass(arg).getDirectSuperclasses();
5216      }
5217    };
5218
5219  // ### %set-class-direct-superclasses
5220  private static final Primitive _SET_CLASS_DIRECT_SUPERCLASSES =
5221    new Primitive("%set-class-direct-superclasses", PACKAGE_SYS, true)
5222    {
5223      @Override
5224      public LispObject execute(LispObject first, LispObject second)
5225        throws ConditionThrowable
5226      {
5227            checkClass(first).setDirectSuperclasses(second);
5228            return second;
5229      }
5230    };
5231
5232  // ### class-direct-subclasses
5233  private static final Primitive CLASS_DIRECT_SUBCLASSES =
5234    new Primitive("class-direct-subclasses", PACKAGE_SYS, true)
5235    {
5236      @Override
5237      public LispObject execute(LispObject arg) throws ConditionThrowable
5238      {
5239            return checkClass(arg).getDirectSubclasses();
5240      }
5241    };
5242
5243  // ### %set-class-direct-subclasses
5244  private static final Primitive _SET_CLASS_DIRECT_SUBCLASSES =
5245    new Primitive("%set-class-direct-subclasses", PACKAGE_SYS, true,
5246                  "class direct-subclasses")
5247    {
5248      @Override
5249      public LispObject execute(LispObject first, LispObject second)
5250        throws ConditionThrowable
5251      {
5252          checkClass(first).setDirectSubclasses(second);
5253          return second;
5254      }
5255    };
5256
5257  // ### %class-precedence-list
5258  private static final Primitive _CLASS_PRECEDENCE_LIST =
5259    new Primitive("%class-precedence-list", PACKAGE_SYS, true)
5260    {
5261      @Override
5262      public LispObject execute(LispObject arg) throws ConditionThrowable
5263      {
5264          return checkClass(arg).getCPL();
5265      }
5266    };
5267
5268  // ### set-class-precedence-list
5269  private static final Primitive SET_CLASS_PRECEDENCE_LIST =
5270    new Primitive("set-class-precedence-list", PACKAGE_SYS, true)
5271    {
5272      @Override
5273      public LispObject execute(LispObject first, LispObject second)
5274        throws ConditionThrowable
5275      {
5276          checkClass(first).classPrecedenceList = second;
5277          return second;
5278      }
5279    };
5280
5281  // ### class-direct-methods
5282  private static final Primitive CLASS_DIRECT_METHODS =
5283    new Primitive("class-direct-methods", PACKAGE_SYS, true)
5284    {
5285      @Override
5286      public LispObject execute(LispObject arg)
5287        throws ConditionThrowable
5288      {
5289          return checkClass(arg).directMethods;
5290      }
5291    };
5292
5293  // ### %set-class-direct-methods
5294  private static final Primitive _SET_CLASS_DIRECT_METHODS =
5295    new Primitive("%set-class-direct-methods", PACKAGE_SYS, true)
5296    {
5297      @Override
5298      public LispObject execute(LispObject first, LispObject second)
5299        throws ConditionThrowable
5300      {
5301          checkClass(first).directMethods = second;
5302          return second;
5303      }
5304    };
5305
5306  // ### class-documentation
5307  private static final Primitive CLASS_DOCUMENTATION =
5308    new Primitive("class-documentation", PACKAGE_SYS, true)
5309    {
5310      @Override
5311      public LispObject execute(LispObject arg)
5312        throws ConditionThrowable
5313      {
5314          return checkClass(arg).documentation;
5315      }
5316    };
5317
5318  // ### %set-class-documentation
5319  private static final Primitive _SET_CLASS_DOCUMENTATION =
5320    new Primitive("%set-class-documentation", PACKAGE_SYS, true)
5321    {
5322      @Override
5323      public LispObject execute(LispObject first, LispObject second)
5324        throws ConditionThrowable
5325      {
5326          checkClass(first).documentation = second;
5327          return second;
5328      }
5329    };
5330
5331  // ### class-finalized-p
5332  private static final Primitive CLASS_FINALIZED_P =
5333    new Primitive("class-finalized-p", PACKAGE_SYS, true)
5334    {
5335      @Override
5336      public LispObject execute(LispObject arg) throws ConditionThrowable
5337      {
5338            return checkClass(arg).isFinalized() ? T : NIL;
5339      }
5340    };
5341
5342  // ### %set-class-finalized-p
5343  private static final Primitive _SET_CLASS_FINALIZED_P =
5344    new Primitive("%set-class-finalized-p", PACKAGE_SYS, true)
5345    {
5346      @Override
5347      public LispObject execute(LispObject first, LispObject second)
5348        throws ConditionThrowable
5349      {
5350          checkClass(first).setFinalized(second != NIL);
5351          return second;
5352      }
5353    };
5354
5355  // ### classp
5356  private static final Primitive CLASSP =
5357    new Primitive("classp", PACKAGE_EXT, true)
5358    {
5359      @Override
5360      public LispObject execute(LispObject arg)
5361      {
5362        return arg instanceof LispClass ? T : NIL;
5363      }
5364    };
5365
5366  // ### char-to-utf8 char => octets
5367  private static final Primitive CHAR_TO_UTF8 =
5368    new Primitive("char-to-utf8", PACKAGE_EXT, true)
5369    {
5370      @Override
5371      public LispObject execute(LispObject arg) throws ConditionThrowable
5372      {
5373        final LispCharacter c;
5374        c = checkCharacter( arg);
5375        char[] chars = new char[1];
5376        chars[0] = c.value;
5377        String s = new String(chars);
5378        final byte[] bytes;
5379        try
5380          {
5381            bytes = s.getBytes("UTF8");
5382          }
5383        catch (java.io.UnsupportedEncodingException e)
5384          {
5385            return error(new LispError("UTF8 is not a supported encoding."));
5386          }
5387        LispObject[] objects = new LispObject[bytes.length];
5388        for (int i = bytes.length; i-- > 0;)
5389          {
5390            int n = bytes[i];
5391            if (n < 0)
5392              n += 256;
5393            objects[i] = Fixnum.getInstance(n);
5394          }
5395        return new SimpleVector(objects);
5396      }
5397    };
5398
5399  // ### %documentation
5400  private static final Primitive _DOCUMENTATION =
5401    new Primitive("%documentation", PACKAGE_SYS, true,
5402                  "object doc-type")
5403    {
5404      @Override
5405      public LispObject execute(LispObject object, LispObject docType)
5406        throws ConditionThrowable
5407      {
5408        LispObject doc = object.getDocumentation(docType);
5409        if (doc == NIL)
5410          {
5411            if (docType == Symbol.FUNCTION && object instanceof Symbol)
5412              {
5413                LispObject function = object.getSymbolFunction();
5414                if (function != null)
5415                  doc = function.getDocumentation(docType);
5416              }
5417          }
5418        return doc;
5419      }
5420    };
5421
5422  // ### %set-documentation
5423  private static final Primitive _SET_DOCUMENTATION =
5424    new Primitive("%set-documentation", PACKAGE_SYS, true,
5425                  "object doc-type documentation")
5426    {
5427      @Override
5428      public LispObject execute(LispObject object, LispObject docType,
5429                                LispObject documentation)
5430        throws ConditionThrowable
5431      {
5432        object.setDocumentation(docType, documentation);
5433        return documentation;
5434      }
5435    };
5436
5437  // ### %putf
5438  private static final Primitive _PUTF =
5439    new Primitive("%putf", PACKAGE_SYS, true,
5440                  "plist indicator new-value")
5441    {
5442      @Override
5443      public LispObject execute(LispObject plist, LispObject indicator,
5444                                LispObject newValue)
5445        throws ConditionThrowable
5446      {
5447        return putf(plist, indicator, newValue);
5448      }
5449    };
5450
5451  // ### function-plist
5452  private static final Primitive FUNCTION_PLIST =
5453    new Primitive("function-plist", PACKAGE_SYS, true, "function")
5454    {
5455      @Override
5456      public LispObject execute(LispObject arg) throws ConditionThrowable
5457      {
5458          return checkFunction(arg).getPropertyList();
5459      }
5460    };
5461
5462  // ### make-keyword
5463  private static final Primitive MAKE_KEYWORD =
5464    new Primitive("make-keyword", PACKAGE_SYS, true, "symbol")
5465    {
5466      @Override
5467      public LispObject execute(LispObject arg) throws ConditionThrowable
5468      {
5469          return PACKAGE_KEYWORD.intern(checkSymbol(arg).name);
5470      }
5471    };
5472
5473  // ### standard-object-p object => generalized-boolean
5474  private static final Primitive STANDARD_OBJECT_P =
5475    new Primitive("standard-object-p", PACKAGE_SYS, true, "object")
5476    {
5477      @Override
5478      public LispObject execute(LispObject arg)
5479      {
5480        return arg instanceof StandardObject ? T : NIL;
5481      }
5482    };
5483
5484  // ### copy-tree
5485  private static final Primitive COPY_TREE =
5486    new Primitive(Symbol.COPY_TREE, "object")
5487    {
5488      @Override
5489      public LispObject execute(LispObject arg)
5490      {
5491        if (arg instanceof Cons)
5492          {
5493            Cons cons = (Cons) arg;
5494            return new Cons(execute(cons.car), execute(cons.cdr));
5495          }
5496        else
5497          return arg;
5498      }
5499    };
5500   
5501}
Note: See TracBrowser for help on using the repository browser.