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

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

Compilation of functions with a non-null
lexical environment part 2 [of 2]: Functions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 164.7 KB
Line 
1/*
2 * Primitives.java
3 *
4 * Copyright (C) 2002-2007 Peter Graves
5 * $Id: Primitives.java 11926 2009-05-22 18:04:53Z 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        final LispObject stack = thread.getStack();
3513        LispObject remaining = args;
3514        while (remaining != NIL)
3515          {
3516            LispObject current = remaining.car();
3517            if (current instanceof Cons)
3518              {
3519                try
3520                  {
3521                    // Handle GO inline if possible.
3522                    if (((Cons)current).car == Symbol.GO)
3523                      {
3524                        if (interrupted)
3525                          handleInterrupt();
3526                        LispObject tag = current.cadr();
3527                        if (memql(tag, localTags))
3528                          {
3529                            Binding binding = ext.getTagBinding(tag);
3530                            if (binding != null && binding.value != null)
3531                              {
3532                                remaining = binding.value;
3533                                continue;
3534                              }
3535                          }
3536                        throw new Go(tag);
3537                      }
3538                    eval(current, ext, thread);
3539                  }
3540                catch (Go go)
3541                  {
3542                    LispObject tag = go.getTag();
3543                    if (memql(tag, localTags))
3544                      {
3545                        Binding binding = ext.getTagBinding(tag);
3546                        if (binding != null && binding.value != null)
3547                          {
3548                            remaining = binding.value;
3549                            thread.setStack(stack);
3550                            continue;
3551                          }
3552                      }
3553                    throw go;
3554                  }
3555              }
3556            remaining = ((Cons)remaining).cdr;
3557          }
3558        thread._values = null;
3559        return NIL;
3560      }
3561    };
3562
3563  // ### go
3564  private static final SpecialOperator GO =
3565    new SpecialOperator(Symbol.GO, "tag")
3566    {
3567      @Override
3568      public LispObject execute(LispObject args, Environment env)
3569        throws ConditionThrowable
3570      {
3571        if (args.length() != 1)
3572          return error(new WrongNumberOfArgumentsException(this));
3573        Binding binding = env.getTagBinding(args.car());
3574        if (binding == null)
3575          return error(new ControlError("No tag named " +
3576                                         args.car().writeToString() +
3577                                         " is currently visible."));
3578        throw new Go(args.car());
3579      }
3580    };
3581
3582  // ### block
3583  private static final SpecialOperator BLOCK =
3584    new SpecialOperator(Symbol.BLOCK, "name &rest forms")
3585    {
3586      @Override
3587      public LispObject execute(LispObject args, Environment env)
3588        throws ConditionThrowable
3589      {
3590        if (args == NIL)
3591          return error(new WrongNumberOfArgumentsException(this));
3592        LispObject tag;
3593            tag = checkSymbol(args.car());
3594        LispObject body = ((Cons)args).cdr();
3595        Environment ext = new Environment(env);
3596        final LispObject block = new LispObject();
3597        ext.addBlock(tag, block);
3598        LispObject result = NIL;
3599        final LispThread thread = LispThread.currentThread();
3600        final LispObject stack = thread.getStack();
3601        try
3602          {
3603            return progn(body, ext, thread);
3604          }
3605        catch (Return ret)
3606          {
3607            if (ret.getBlock() == block)
3608              {
3609                thread.setStack(stack);
3610                return ret.getResult();
3611              }
3612            throw ret;
3613          }
3614      }
3615    };
3616
3617  // ### return-from
3618  private static final SpecialOperator RETURN_FROM =
3619    new SpecialOperator(Symbol.RETURN_FROM, "name &optional value")
3620    {
3621      @Override
3622      public LispObject execute(LispObject args, Environment env)
3623        throws ConditionThrowable
3624      {
3625        final int length = args.length();
3626        if (length < 1 || length > 2)
3627          return error(new WrongNumberOfArgumentsException(this));
3628        Symbol symbol;
3629            symbol = checkSymbol(args.car());
3630
3631        LispObject block = env.lookupBlock(symbol);
3632        if (block == null)
3633          {
3634            FastStringBuffer sb = new FastStringBuffer("No block named ");
3635            sb.append(symbol.getName());
3636            sb.append(" is currently visible.");
3637            error(new LispError(sb.toString()));
3638          }
3639        LispObject result;
3640        if (length == 2)
3641          result = eval(args.cadr(), env, LispThread.currentThread());
3642        else
3643          result = NIL;
3644        throw new Return(symbol, block, result);
3645      }
3646    };
3647
3648  // ### catch
3649  private static final SpecialOperator CATCH =
3650    new SpecialOperator(Symbol.CATCH, "tag &body body")
3651    {
3652      @Override
3653      public LispObject execute(LispObject args, Environment env)
3654        throws ConditionThrowable
3655      {
3656        if (args.length() < 1)
3657          return error(new WrongNumberOfArgumentsException(this));
3658        final LispThread thread = LispThread.currentThread();
3659        LispObject tag = eval(args.car(), env, thread);
3660        thread.pushCatchTag(tag);
3661        LispObject body = args.cdr();
3662        LispObject result = NIL;
3663        final LispObject stack = thread.getStack();
3664        try
3665          {
3666            return progn(body, env, thread);
3667          }
3668        catch (Throw t)
3669          {
3670            if (t.tag == tag)
3671              {
3672                thread.setStack(stack);
3673                return t.getResult(thread);
3674              }
3675            throw t;
3676          }
3677        catch (Return ret)
3678          {
3679            throw ret;
3680          }
3681        finally
3682          {
3683            thread.popCatchTag();
3684          }
3685      }
3686    };
3687
3688  // ### throw
3689  private static final SpecialOperator THROW =
3690    new SpecialOperator(Symbol.THROW, "tag result")
3691    {
3692      @Override
3693      public LispObject execute(LispObject args, Environment env)
3694        throws ConditionThrowable
3695      {
3696        if (args.length() != 2)
3697          return error(new WrongNumberOfArgumentsException(this));
3698        final LispThread thread = LispThread.currentThread();
3699        thread.throwToTag(eval(args.car(), env, thread),
3700                          eval(args.cadr(), env, thread));
3701        // Not reached.
3702        return NIL;
3703      }
3704    };
3705
3706  // ### unwind-protect
3707  private static final SpecialOperator UNWIND_PROTECT =
3708    new SpecialOperator(Symbol.UNWIND_PROTECT, "protected &body cleanup")
3709    {
3710      @Override
3711      public LispObject execute(LispObject args, Environment env)
3712        throws ConditionThrowable
3713      {
3714        final LispThread thread = LispThread.currentThread();
3715        LispObject result;
3716        LispObject[] values;
3717        try
3718          {
3719            result = eval(args.car(), env, thread);
3720            values = thread._values;
3721          }
3722        finally
3723          {
3724            LispObject body = args.cdr();
3725            while (body != NIL)
3726              {
3727                eval(body.car(), env, thread);
3728                body = ((Cons)body).cdr;
3729              }
3730          }
3731        if (values != null)
3732          thread.setValues(values);
3733        else
3734          thread._values = null;
3735        return result;
3736      }
3737    };
3738
3739  // ### eval-when
3740  private static final SpecialOperator EVAL_WHEN =
3741    new SpecialOperator(Symbol.EVAL_WHEN, "situations &rest forms")
3742    {
3743      @Override
3744      public LispObject execute(LispObject args, Environment env)
3745        throws ConditionThrowable
3746      {
3747        LispObject situations = args.car();
3748        if (situations != NIL)
3749          {
3750            if (memq(Keyword.EXECUTE, situations) ||
3751                memq(Symbol.EVAL, situations))
3752              {
3753                return progn(args.cdr(), env, LispThread.currentThread());
3754              }
3755          }
3756        return NIL;
3757      }
3758    };
3759
3760  // ### multiple-value-bind
3761  // multiple-value-bind (var*) values-form declaration* form*
3762  // Should be a macro.
3763  private static final SpecialOperator MULTIPLE_VALUE_BIND =
3764    new SpecialOperator(Symbol.MULTIPLE_VALUE_BIND,
3765                        "vars value-form &body body")
3766    {
3767      @Override
3768      public LispObject execute(LispObject args, Environment env)
3769        throws ConditionThrowable
3770      {
3771        LispObject vars = args.car();
3772        args = args.cdr();
3773        LispObject valuesForm = args.car();
3774        LispObject body = args.cdr();
3775        final LispThread thread = LispThread.currentThread();
3776        LispObject value = eval(valuesForm, env, thread);
3777        LispObject[] values = thread._values;
3778        if (values == null)
3779          {
3780            // eval() did not return multiple values.
3781            values = new LispObject[1];
3782            values[0] = value;
3783          }
3784        // Process declarations.
3785        LispObject bodyAndDecls = parseBody(body, false);
3786        LispObject specials = parseSpecials(bodyAndDecls.NTH(1));
3787        body = bodyAndDecls.car();
3788
3789        final SpecialBinding lastSpecialBinding = thread.lastSpecialBinding;
3790        final Environment ext = new Environment(env);
3791        int i = 0;
3792        LispObject var = vars.car();
3793        while (var != NIL)
3794          {
3795            final Symbol sym;
3796
3797            sym =  checkSymbol(var);
3798
3799            LispObject val = i < values.length ? values[i] : NIL;
3800            if (specials != NIL && memq(sym, specials))
3801              {
3802                thread.bindSpecial(sym, val);
3803                ext.declareSpecial(sym);
3804              }
3805            else if (sym.isSpecialVariable())
3806              {
3807                thread.bindSpecial(sym, val);
3808              }
3809            else
3810              ext.bind(sym, val);
3811            vars = vars.cdr();
3812            var = vars.car();
3813            ++i;
3814          }
3815        // Make sure free special declarations are visible in the body.
3816        // "The scope of free declarations specifically does not include
3817        // initialization forms for bindings established by the form
3818        // containing the declarations." (3.3.4)
3819        while (specials != NIL)
3820          {
3821            Symbol symbol = (Symbol) specials.car();
3822            ext.declareSpecial(symbol);
3823            specials = ((Cons)specials).cdr;
3824          }
3825        thread._values = null;
3826        LispObject result = NIL;
3827        try
3828          {
3829            result  = progn(body, ext, thread);
3830          }
3831        finally
3832          {
3833            thread.lastSpecialBinding = lastSpecialBinding;
3834          }
3835        return result;
3836      }
3837    };
3838
3839  // ### multiple-value-prog1
3840  private static final SpecialOperator MULTIPLE_VALUE_PROG1 =
3841    new SpecialOperator(Symbol.MULTIPLE_VALUE_PROG1,
3842                        "values-form &rest forms")
3843    {
3844      @Override
3845      public LispObject execute(LispObject args, Environment env)
3846        throws ConditionThrowable
3847      {
3848        if (args.length() == 0)
3849          return error(new WrongNumberOfArgumentsException(this));
3850        final LispThread thread = LispThread.currentThread();
3851        LispObject result = eval(args.car(), env, thread);
3852        LispObject[] values = thread._values;
3853        while ((args = args.cdr()) != NIL)
3854          eval(args.car(), env, thread);
3855        if (values != null)
3856          thread.setValues(values);
3857        else
3858          thread._values = null;
3859        return result;
3860      }
3861    };
3862
3863  // ### multiple-value-call
3864  private static final SpecialOperator MULTIPLE_VALUE_CALL =
3865    new SpecialOperator(Symbol.MULTIPLE_VALUE_CALL, "fun &rest args")
3866    {
3867      @Override
3868      public LispObject execute(LispObject args, Environment env)
3869        throws ConditionThrowable
3870      {
3871        if (args.length() == 0)
3872          return error(new WrongNumberOfArgumentsException(this));
3873        final LispThread thread = LispThread.currentThread();
3874        LispObject function;
3875        LispObject obj = eval(args.car(), env, thread);
3876        args = args.cdr();
3877        if (obj instanceof Symbol)
3878          {
3879            function = obj.getSymbolFunction();
3880            if (function == null)
3881              error(new UndefinedFunction(obj));
3882          }
3883        else if (obj instanceof Function)
3884          {
3885            function = obj;
3886          }
3887        else
3888          {
3889            error(new LispError(obj.writeToString() +
3890                                 " is not a function name."));
3891            return NIL;
3892          }
3893        ArrayList<LispObject> arrayList = new ArrayList<LispObject>();
3894        while (args != NIL)
3895          {
3896            LispObject form = args.car();
3897            LispObject result = eval(form, env, thread);
3898            LispObject[] values = thread._values;
3899            if (values != null)
3900              {
3901                for (int i = 0; i < values.length; i++)
3902                  arrayList.add(values[i]);
3903              }
3904            else
3905              arrayList.add(result);
3906            args = ((Cons)args).cdr;
3907          }
3908        LispObject[] argv = new LispObject[arrayList.size()];
3909        arrayList.toArray(argv);
3910        return funcall(function, argv, thread);
3911      }
3912    };
3913
3914  // ### and
3915  // Should be a macro.
3916  private static final SpecialOperator AND =
3917    new SpecialOperator(Symbol.AND, "&rest forms")
3918    {
3919      @Override
3920      public LispObject execute(LispObject args, Environment env)
3921        throws ConditionThrowable
3922      {
3923        final LispThread thread = LispThread.currentThread();
3924        LispObject result = T;
3925        while (args != NIL)
3926          {
3927            result = eval(args.car(), env, thread);
3928            if (result == NIL)
3929              {
3930                if (((Cons)args).cdr != NIL)
3931                  {
3932                    // Not the last form.
3933                    thread._values = null;
3934                  }
3935                break;
3936              }
3937            args = ((Cons)args).cdr;
3938          }
3939        return result;
3940      }
3941    };
3942
3943  // ### or
3944  // Should be a macro.
3945  private static final SpecialOperator OR =
3946    new SpecialOperator(Symbol.OR, "&rest forms")
3947    {
3948      @Override
3949      public LispObject execute(LispObject args, Environment env)
3950        throws ConditionThrowable
3951      {
3952        final LispThread thread = LispThread.currentThread();
3953        LispObject result = NIL;
3954        while (args != NIL)
3955          {
3956            result = eval(args.car(), env, thread);
3957            if (result != NIL)
3958              {
3959                if (((Cons)args).cdr != NIL)
3960                  {
3961                    // Not the last form.
3962                    thread._values = null;
3963                  }
3964                break;
3965              }
3966            args = ((Cons)args).cdr;
3967          }
3968        return result;
3969      }
3970    };
3971
3972  // ### multiple-value-list form => list
3973  // Evaluates form and creates a list of the multiple values it returns.
3974  // Should be a macro.
3975  private static final SpecialOperator MULTIPLE_VALUE_LIST =
3976    new SpecialOperator(Symbol.MULTIPLE_VALUE_LIST, "value-form")
3977    {
3978      @Override
3979      public LispObject execute(LispObject args, Environment env)
3980        throws ConditionThrowable
3981      {
3982        if (args.length() != 1)
3983          return error(new WrongNumberOfArgumentsException(this));
3984        final LispThread thread = LispThread.currentThread();
3985        LispObject result = eval(((Cons)args).car, env, thread);
3986        LispObject[] values = thread._values;
3987        if (values == null)
3988          return new Cons(result);
3989        thread._values = null;
3990        LispObject list = NIL;
3991        for (int i = values.length; i-- > 0;)
3992          list = new Cons(values[i], list);
3993        return list;
3994      }
3995    };
3996
3997  // ### nth-value n form => object
3998  // Evaluates n and then form and returns the nth value returned by form, or
3999  // NIL if n >= number of values returned.
4000  // Should be a macro.
4001  private static final SpecialOperator NTH_VALUE =
4002    new SpecialOperator(Symbol.NTH_VALUE, "n form")
4003    {
4004      @Override
4005      public LispObject execute(LispObject args, Environment env)
4006        throws ConditionThrowable
4007      {
4008        if (args.length() != 2)
4009          return error(new WrongNumberOfArgumentsException(this));
4010        final LispThread thread = LispThread.currentThread();
4011        int n = Fixnum.getValue(eval(args.car(), env, thread));
4012        if (n < 0)
4013          n = 0;
4014        LispObject result = eval(args.cadr(), env, thread);
4015        LispObject[] values = thread._values;
4016        thread._values = null;
4017        if (values == null)
4018          {
4019            // A single value was returned.
4020            return n == 0 ? result : NIL;
4021          }
4022        if (n < values.length)
4023          return values[n];
4024        return NIL;
4025      }
4026    };
4027
4028  // ### call-count
4029  private static final Primitive CALL_COUNT =
4030    new Primitive("call-count", PACKAGE_SYS, true)
4031    {
4032      @Override
4033      public LispObject execute(LispObject arg) throws ConditionThrowable
4034      {
4035        return Fixnum.getInstance(arg.getCallCount());
4036      }
4037    };
4038
4039  // ### set-call-count
4040  private static final Primitive SET_CALL_COUNT =
4041    new Primitive("set-call-count", PACKAGE_SYS, true)
4042    {
4043      @Override
4044      public LispObject execute(LispObject first, LispObject second)
4045        throws ConditionThrowable
4046      {
4047        first.setCallCount(Fixnum.getValue(second));
4048        return second;
4049      }
4050    };
4051
4052  // ### lambda-name
4053  private static final Primitive LAMBDA_NAME =
4054    new Primitive("lambda-name", PACKAGE_SYS, true)
4055    {
4056      @Override
4057      public LispObject execute(LispObject arg) throws ConditionThrowable
4058      {
4059        if (arg instanceof Operator)
4060          {
4061            return ((Operator)arg).getLambdaName();
4062          }
4063        if (arg instanceof StandardGenericFunction)
4064          {
4065            return ((StandardGenericFunction)arg).getGenericFunctionName();
4066          }
4067        return type_error(arg, Symbol.FUNCTION);
4068      }
4069    };
4070
4071  // ### %set-lambda-name
4072  private static final Primitive _SET_LAMBDA_NAME =
4073    new Primitive("%set-lambda-name", PACKAGE_SYS, false)
4074    {
4075      @Override
4076      public LispObject execute(LispObject first, LispObject second)
4077        throws ConditionThrowable
4078      {
4079        if (first instanceof Operator)
4080          {
4081            ((Operator)first).setLambdaName(second);
4082            return second;
4083          }
4084        if (first instanceof StandardGenericFunction)
4085          {
4086            ((StandardGenericFunction)first).setGenericFunctionName(second);
4087            return second;
4088          }
4089        return type_error(first, Symbol.FUNCTION);
4090      }
4091    };
4092
4093  // ### shrink-vector vector new-size => vector
4094  // Destructively alters the vector, changing its length to NEW-SIZE, which
4095  // must be less than or equal to its current length.
4096  // shrink-vector vector new-size => vector
4097  private static final Primitive SHRINK_VECTOR =
4098    new Primitive("shrink-vector", PACKAGE_SYS, true, "vector new-size")
4099    {
4100      @Override
4101      public LispObject execute(LispObject first, LispObject second)
4102        throws ConditionThrowable
4103      {
4104        checkVector(first).shrink(Fixnum.getValue(second));
4105        return first;
4106      }
4107    };
4108
4109  // ### subseq sequence start &optional end
4110  private static final Primitive SUBSEQ =
4111    new Primitive(Symbol.SUBSEQ, "sequence start &optional end")
4112    {
4113      @Override
4114      public LispObject execute(LispObject first, LispObject second)
4115        throws ConditionThrowable
4116      {
4117        final int start = Fixnum.getValue(second);
4118        if (start < 0)
4119          {
4120            FastStringBuffer sb = new FastStringBuffer("Bad start index (");
4121            sb.append(start);
4122            sb.append(") for SUBSEQ.");
4123            error(new TypeError(sb.toString()));
4124          }
4125        if (first.listp())
4126          return list_subseq(first, start, -1);
4127        if (first instanceof AbstractVector)
4128          {
4129            final AbstractVector v = (AbstractVector) first;
4130            return v.subseq(start, v.length());
4131          }
4132        return type_error(first, Symbol.SEQUENCE);
4133      }
4134      @Override
4135      public LispObject execute(LispObject first, LispObject second,
4136                                LispObject third)
4137        throws ConditionThrowable
4138      {
4139        final int start = Fixnum.getValue(second);
4140        if (start < 0)
4141          {
4142            FastStringBuffer sb = new FastStringBuffer("Bad start index (");
4143            sb.append(start);
4144            sb.append(").");
4145            error(new TypeError(sb.toString()));
4146          }
4147        int end;
4148        if (third != NIL)
4149          {
4150            end = Fixnum.getValue(third);
4151            if (start > end)
4152              {
4153                FastStringBuffer sb = new FastStringBuffer("Start index (");
4154                sb.append(start);
4155                sb.append(") is greater than end index (");
4156                sb.append(end);
4157                sb.append(") for SUBSEQ.");
4158                error(new TypeError(sb.toString()));
4159              }
4160          }
4161        else
4162          end = -1;
4163        if (first.listp())
4164          return list_subseq(first, start, end);
4165        if (first instanceof AbstractVector)
4166          {
4167            final AbstractVector v = (AbstractVector) first;
4168            if (end < 0)
4169              end = v.length();
4170            return v.subseq(start, end);
4171          }
4172        return type_error(first, Symbol.SEQUENCE);
4173      }
4174    };
4175
4176  private static final LispObject list_subseq(LispObject list, int start,
4177                                              int end)
4178    throws ConditionThrowable
4179  {
4180    int index = 0;
4181    LispObject result = NIL;
4182    while (list != NIL)
4183      {
4184        if (end >= 0 && index == end)
4185          return result.nreverse();
4186        if (index++ >= start)
4187          result = new Cons(list.car(), result);
4188        list = list.cdr();
4189      }
4190    return result.nreverse();
4191  }
4192
4193  // ### list
4194  private static final Primitive LIST =
4195    new Primitive(Symbol.LIST, "&rest objects")
4196    {
4197      @Override
4198      public LispObject execute()
4199      {
4200        return NIL;
4201      }
4202      @Override
4203      public LispObject execute(LispObject arg)
4204      {
4205        return new Cons(arg);
4206      }
4207      @Override
4208      public LispObject execute(LispObject first, LispObject second)
4209      {
4210        return new Cons(first, new Cons(second));
4211      }
4212      @Override
4213      public LispObject execute(LispObject first, LispObject second,
4214                                LispObject third)
4215      {
4216        return new Cons(first, new Cons(second, new Cons(third)));
4217      }
4218      @Override
4219      public LispObject execute(LispObject first, LispObject second,
4220                                LispObject third, LispObject fourth)
4221      {
4222        return new Cons(first,
4223                        new Cons(second,
4224                                 new Cons(third,
4225                                          new Cons(fourth))));
4226      }
4227      @Override
4228      public LispObject execute(LispObject[] args) throws ConditionThrowable
4229      {
4230        LispObject result = NIL;
4231        for (int i = args.length; i-- > 0;)
4232          result = new Cons(args[i], result);
4233        return result;
4234      }
4235    };
4236
4237  // ### list*
4238  private static final Primitive LIST_STAR =
4239    new Primitive(Symbol.LIST_STAR, "&rest objects")
4240    {
4241      @Override
4242      public LispObject execute() throws ConditionThrowable
4243      {
4244        return error(new WrongNumberOfArgumentsException(this));
4245      }
4246      @Override
4247      public LispObject execute(LispObject arg) throws ConditionThrowable
4248      {
4249        return arg;
4250      }
4251      @Override
4252      public LispObject execute(LispObject first, LispObject second)
4253        throws ConditionThrowable
4254      {
4255        return new Cons(first, second);
4256      }
4257      @Override
4258      public LispObject execute(LispObject first, LispObject second,
4259                                LispObject third)
4260        throws ConditionThrowable
4261      {
4262        return new Cons(first, new Cons(second, third));
4263      }
4264      @Override
4265      public LispObject execute(LispObject first, LispObject second,
4266                                LispObject third, LispObject fourth)
4267        throws ConditionThrowable
4268      {
4269        return new Cons(first,
4270                        new Cons(second,
4271                                 new Cons(third, fourth)));
4272      }
4273      @Override
4274      public LispObject execute(LispObject[] args) throws ConditionThrowable
4275      {
4276        int i = args.length - 1;
4277        LispObject result = args[i];
4278        while (i-- > 0)
4279          result = new Cons(args[i], result);
4280        return result;
4281      }
4282    };
4283
4284  // ### nreverse
4285  public static final Primitive NREVERSE =
4286    new Primitive(Symbol.NREVERSE, "sequence")
4287    {
4288      @Override
4289      public LispObject execute (LispObject arg) throws ConditionThrowable
4290      {
4291        return arg.nreverse();
4292      }
4293    };
4294
4295  // ### nreconc
4296  private static final Primitive NRECONC =
4297    new Primitive(Symbol.NRECONC, "list tail")
4298    {
4299      @Override
4300      public LispObject execute(LispObject list, LispObject obj)
4301        throws ConditionThrowable
4302      {
4303        if (list instanceof Cons)
4304          {
4305            LispObject list3 = list.cdr();
4306            if (list3 instanceof Cons)
4307              {
4308                if (list3.cdr() instanceof Cons)
4309                  {
4310                    LispObject list1 = list3;
4311                    LispObject list2 = NIL;
4312                    do
4313                      {
4314                        LispObject h = list3.cdr();
4315                        list3.setCdr(list2);
4316                        list2 = list3;
4317                        list3 = h;
4318                      } while (list3.cdr() instanceof Cons);
4319                    list.setCdr(list2);
4320                    list1.setCdr(list3);
4321                  }
4322                LispObject h = list.car();
4323                list.setCar(list3.car());
4324                list3.setCar(h);
4325                list3.setCdr(obj);
4326              }
4327            else if (list3 == NIL)
4328              {
4329                list.setCdr(obj);
4330              }
4331            else
4332              type_error(list3, Symbol.LIST);
4333            return list;
4334          }
4335        else if (list == NIL)
4336          return obj;
4337        else
4338          return type_error(list, Symbol.LIST);
4339      }
4340    };
4341
4342  // ### reverse
4343  private static final Primitive REVERSE =
4344    new Primitive(Symbol.REVERSE, "sequence")
4345    {
4346      @Override
4347      public LispObject execute(LispObject arg) throws ConditionThrowable
4348      {
4349        return arg.reverse();
4350      }
4351    };
4352
4353  // ### delete-eq item sequence => result-sequence
4354  private static final Primitive DELETE_EQ =
4355    new Primitive("delete-eq", PACKAGE_SYS, true, "item sequence")
4356    {
4357      @Override
4358      public LispObject execute(LispObject item, LispObject sequence)
4359        throws ConditionThrowable
4360      {
4361        if (sequence instanceof AbstractVector)
4362          return ((AbstractVector)sequence).deleteEq(item);
4363        else
4364          return LIST_DELETE_EQ.execute(item, sequence);
4365      }
4366    };
4367
4368  // ### delete-eql item seqluence => result-seqluence
4369  private static final Primitive DELETE_EQL =
4370    new Primitive("delete-eql", PACKAGE_SYS, true, "item sequence")
4371    {
4372      @Override
4373      public LispObject execute(LispObject item, LispObject sequence)
4374        throws ConditionThrowable
4375      {
4376        if (sequence instanceof AbstractVector)
4377          return ((AbstractVector)sequence).deleteEql(item);
4378        else
4379          return LIST_DELETE_EQL.execute(item, sequence);
4380      }
4381    };
4382
4383  // ### list-delete-eq item list => result-list
4384  private static final Primitive LIST_DELETE_EQ =
4385    new Primitive("list-delete-eq", PACKAGE_SYS, true, "item list")
4386    {
4387      @Override
4388      public LispObject execute(LispObject item, LispObject list)
4389        throws ConditionThrowable
4390      {
4391        if (list instanceof Cons)
4392          {
4393            LispObject tail = list;
4394            LispObject splice = list;
4395            while (tail instanceof Cons)
4396              {
4397                LispObject car = tail.car();
4398                if (car == item)
4399                  {
4400                    if (tail.cdr() != NIL)
4401                      {
4402                        LispObject temp = tail;
4403                        tail.setCar(temp.cadr());
4404                        tail.setCdr(temp.cddr());
4405                      }
4406                    else
4407                      {
4408                        // Last item.
4409                        if (tail == list)
4410                          return NIL;
4411                        splice.setCdr(NIL);
4412                        return list;
4413                      }
4414                  }
4415                else
4416                  {
4417                    splice = tail;
4418                    tail = tail.cdr();
4419                  }
4420              }
4421            if (tail == NIL)
4422              return list;
4423            else
4424              return type_error(tail, Symbol.LIST);
4425          }
4426        else if (list == NIL)
4427          return list;
4428        else
4429          return type_error(list, Symbol.LIST);
4430      }
4431    };
4432
4433  // ### list-delete-eql item list => result-list
4434  private static final Primitive LIST_DELETE_EQL =
4435    new Primitive("list-delete-eql", PACKAGE_SYS, true, "item list")
4436    {
4437      @Override
4438      public LispObject execute(LispObject item, LispObject list)
4439        throws ConditionThrowable
4440      {
4441        if (list instanceof Cons)
4442          {
4443            LispObject tail = list;
4444            LispObject splice = list;
4445            while (tail instanceof Cons)
4446              {
4447                LispObject car = tail.car();
4448                if (car.eql(item))
4449                  {
4450                    if (tail.cdr() != NIL)
4451                      {
4452                        LispObject temp = tail;
4453                        tail.setCar(temp.cadr());
4454                        tail.setCdr(temp.cddr());
4455                      }
4456                    else
4457                      {
4458                        // Last item.
4459                        if (tail == list)
4460                          return NIL;
4461                        splice.setCdr(NIL);
4462                        return list;
4463                      }
4464                  }
4465                else
4466                  {
4467                    splice = tail;
4468                    tail = tail.cdr();
4469                  }
4470              }
4471            if (tail == NIL)
4472              return list;
4473            else
4474              return type_error(tail, Symbol.LIST);
4475          }
4476        else if (list == NIL)
4477          return list;
4478        else
4479          return type_error(list, Symbol.LIST);
4480      }
4481    };
4482
4483  // ### vector-delete-eq item vector => result-vector
4484  private static final Primitive VECTOR_DELETE_EQ =
4485    new Primitive("vector-delete-eq", PACKAGE_SYS, true, "item vector")
4486    {
4487      @Override
4488      public LispObject execute(LispObject item, LispObject vector)
4489        throws ConditionThrowable
4490      {
4491          checkVector(vector).deleteEq(item);
4492          return vector;
4493      }
4494    };
4495
4496  // ### vector-delete-eql item vector => result-vector
4497  private static final Primitive VECTOR_DELETE_EQL =
4498    new Primitive("vector-delete-eql", PACKAGE_SYS, true, "item vector")
4499    {
4500      @Override
4501      public LispObject execute(LispObject item, LispObject vector)
4502        throws ConditionThrowable
4503      {
4504          checkVector(vector).deleteEql(item);
4505          return vector;
4506      }
4507    };
4508
4509  // ### %set-elt
4510  // %setelt sequence index newval => newval
4511  private static final Primitive _SET_ELT =
4512    new Primitive("%set-elt", PACKAGE_SYS, false)
4513    {
4514      @Override
4515      public LispObject execute(LispObject first, LispObject second,
4516                                LispObject third)
4517        throws ConditionThrowable
4518      {
4519        if (first instanceof AbstractVector)
4520          {
4521            ((AbstractVector)first).aset(Fixnum.getValue(second), third);
4522            return third;
4523          }
4524        if (first instanceof Cons)
4525          {
4526            int index = Fixnum.getValue(second);
4527            if (index < 0)
4528              error(new TypeError());
4529            LispObject list = first;
4530            int i = 0;
4531            while (true)
4532              {
4533                if (i == index)
4534                  {
4535                    list.setCar(third);
4536                    return third;
4537                  }
4538                list = list.cdr();
4539                if (list == NIL)
4540                  error(new TypeError());
4541                ++i;
4542              }
4543          }
4544        return type_error(first, Symbol.SEQUENCE);
4545      }
4546    };
4547
4548  // ### %make-list
4549  private static final Primitive _MAKE_LIST =
4550    new Primitive("%make-list", PACKAGE_SYS, true)
4551    {
4552      @Override
4553      public LispObject execute(LispObject first, LispObject second)
4554        throws ConditionThrowable
4555      {
4556        int size = Fixnum.getValue(first);
4557        if (size < 0)
4558          return type_error(first, list(Symbol.INTEGER, Fixnum.ZERO,
4559                                              Symbol.MOST_POSITIVE_FIXNUM.getSymbolValue()));
4560        LispObject result = NIL;
4561        for (int i = size; i-- > 0;)
4562          result = new Cons(second, result);
4563        return result;
4564      }
4565    };
4566
4567  // ### %member item list key test test-not => tail
4568  private static final Primitive _MEMBER =
4569    new Primitive("%member", PACKAGE_SYS, true)
4570    {
4571      @Override
4572      public LispObject execute(LispObject item, LispObject list,
4573                                LispObject key, LispObject test,
4574                                LispObject testNot)
4575        throws ConditionThrowable
4576      {
4577        LispObject tail = checkList(list);
4578        if (test != NIL && testNot != NIL)
4579          error(new LispError("MEMBER: test and test-not both supplied"));
4580        if (testNot == NIL)
4581          {
4582            if (test == NIL || test == Symbol.EQL)
4583              test = EQL;
4584          }
4585        if (key == NIL)
4586          {
4587            if (test == EQL)
4588              {
4589                while (tail instanceof Cons)
4590                  {
4591                    if (item.eql(((Cons)tail).car))
4592                      return tail;
4593                    tail = ((Cons)tail).cdr;
4594                  }
4595              }
4596            else if (test != NIL)
4597              {
4598                while (tail instanceof Cons)
4599                  {
4600                    LispObject candidate = ((Cons)tail).car;
4601                    if (test.execute(item, candidate) != NIL)
4602                      return tail;
4603                    tail = ((Cons)tail).cdr;
4604                  }
4605              }
4606            else
4607              {
4608                // test == NIL
4609                while (tail instanceof Cons)
4610                  {
4611                    LispObject candidate = ((Cons)tail).car;
4612                    if (testNot.execute(item, candidate) == NIL)
4613                      return tail;
4614                    tail = ((Cons)tail).cdr;
4615                  }
4616              }
4617          }
4618        else
4619          {
4620            // key != NIL
4621            while (tail instanceof Cons)
4622              {
4623                LispObject candidate = key.execute(((Cons)tail).car);
4624                if (test != NIL)
4625                  {
4626                    if (test.execute(item, candidate) != NIL)
4627                      return tail;
4628                  }
4629                else
4630                  {
4631                    if (testNot.execute(item, candidate) == NIL)
4632                      return tail;
4633                  }
4634                tail = ((Cons)tail).cdr;
4635              }
4636          }
4637        if (tail != NIL)
4638          type_error(tail, Symbol.LIST);
4639        return NIL;
4640      }
4641    };
4642
4643  // ### funcall-key function-or-nil element
4644  private static final Primitive FUNCALL_KEY =
4645    new Primitive("funcall-key", PACKAGE_SYS, false)
4646    {
4647      @Override
4648      public LispObject execute(LispObject first, LispObject second)
4649        throws ConditionThrowable
4650      {
4651        if (first != NIL)
4652          return LispThread.currentThread().execute(first, second);
4653        return second;
4654      }
4655    };
4656
4657  // ### coerce-to-function
4658  private static final Primitive COERCE_TO_FUNCTION =
4659    new Primitive("coerce-to-function", PACKAGE_SYS, true)
4660    {
4661      @Override
4662      public LispObject execute(LispObject arg) throws ConditionThrowable
4663      {
4664        return coerceToFunction(arg);
4665      }
4666    };
4667
4668  // ### make-closure lambda-form environment => closure
4669  private static final Primitive MAKE_CLOSURE =
4670    new Primitive("make-closure", PACKAGE_SYS, true)
4671    {
4672      @Override
4673      public LispObject execute(LispObject first, LispObject second)
4674        throws ConditionThrowable
4675      {
4676        if (first instanceof Cons && ((Cons)first).car == Symbol.LAMBDA)
4677          {
4678            final Environment env;
4679            if (second == NIL)
4680              env = new Environment();
4681            else
4682              env = checkEnvironment(second);
4683            return new Closure(first, env);
4684          }
4685        return error(new TypeError("The argument to MAKE-CLOSURE is not a lambda form."));
4686      }
4687    };
4688
4689  // ### streamp
4690  private static final Primitive STREAMP =
4691    new Primitive(Symbol.STREAMP, "object")
4692    {
4693      @Override
4694      public LispObject execute(LispObject arg)
4695      {
4696        return arg instanceof Stream ? T : NIL;
4697      }
4698    };
4699
4700  // ### integerp
4701  private static final Primitive INTEGERP =
4702    new Primitive(Symbol.INTEGERP, "object")
4703    {
4704      @Override
4705      public LispObject execute(LispObject arg)
4706      {
4707        return arg.INTEGERP();
4708      }
4709    };
4710
4711  // ### evenp
4712  private static final Primitive EVENP =
4713    new Primitive(Symbol.EVENP, "integer")
4714    {
4715      @Override
4716      public LispObject execute(LispObject arg) throws ConditionThrowable
4717      {
4718        return arg.EVENP();
4719      }
4720    };
4721
4722  // ### oddp
4723  private static final Primitive ODDP = new Primitive(Symbol.ODDP, "integer")
4724    {
4725      @Override
4726      public LispObject execute(LispObject arg) throws ConditionThrowable
4727      {
4728        return arg.ODDP();
4729      }
4730    };
4731
4732  // ### numberp
4733  private static final Primitive NUMBERP =
4734    new Primitive(Symbol.NUMBERP, "object")
4735    {
4736      @Override
4737      public LispObject execute(LispObject arg)
4738      {
4739        return arg.NUMBERP();
4740      }
4741    };
4742
4743  // ### realp
4744  private static final Primitive REALP =
4745    new Primitive(Symbol.REALP, "object")
4746    {
4747      @Override
4748      public LispObject execute(LispObject arg)
4749      {
4750        return arg.REALP();
4751      }
4752    };
4753
4754  // ### rationalp
4755  private static final Primitive RATIONALP =
4756    new Primitive(Symbol.RATIONALP,"object")
4757    {
4758      @Override
4759      public LispObject execute(LispObject arg)
4760      {
4761        return arg.RATIONALP();
4762      }
4763    };
4764
4765  // ### complex
4766  private static final Primitive COMPLEX =
4767    new Primitive(Symbol.COMPLEX, "realpart &optional imagpart")
4768    {
4769      @Override
4770      public LispObject execute(LispObject arg) throws ConditionThrowable
4771      {
4772        if (arg instanceof SingleFloat)
4773          return Complex.getInstance(arg, SingleFloat.ZERO);
4774        if (arg instanceof DoubleFloat)
4775          return Complex.getInstance(arg, DoubleFloat.ZERO);
4776        if (arg.realp())
4777          return arg;
4778        return type_error(arg, Symbol.REAL);
4779      }
4780      @Override
4781      public LispObject execute(LispObject first, LispObject second)
4782        throws ConditionThrowable
4783      {
4784        return Complex.getInstance(first, second);
4785      }
4786    };
4787
4788  // ### complexp
4789  private static final Primitive COMPLEXP =
4790    new Primitive(Symbol.COMPLEXP, "object")
4791    {
4792      @Override
4793      public LispObject execute(LispObject arg)
4794      {
4795        return arg.COMPLEXP();
4796      }
4797    };
4798
4799  // ### numerator
4800  private static final Primitive NUMERATOR =
4801    new Primitive(Symbol.NUMERATOR, "rational")
4802    {
4803      @Override
4804      public LispObject execute(LispObject arg) throws ConditionThrowable
4805      {
4806        return arg.NUMERATOR();
4807      }
4808    };
4809
4810  // ### denominator
4811  private static final Primitive DENOMINATOR =
4812    new Primitive(Symbol.DENOMINATOR, "rational")
4813    {
4814      @Override
4815      public LispObject execute(LispObject arg) throws ConditionThrowable
4816      {
4817        return arg.DENOMINATOR();
4818      }
4819    };
4820
4821  // ### realpart
4822  private static final Primitive REALPART =
4823    new Primitive(Symbol.REALPART, "number")
4824    {
4825      @Override
4826      public LispObject execute(LispObject arg) throws ConditionThrowable
4827      {
4828        if (arg instanceof Complex)
4829          return ((Complex)arg).getRealPart();
4830        if (arg.numberp())
4831          return arg;
4832        return type_error(arg, Symbol.NUMBER);
4833      }
4834    };
4835
4836  // ### imagpart
4837  private static final Primitive IMAGPART =
4838    new Primitive(Symbol.IMAGPART, "number")
4839    {
4840      @Override
4841      public LispObject execute(LispObject arg) throws ConditionThrowable
4842      {
4843        if (arg instanceof Complex)
4844          return ((Complex)arg).getImaginaryPart();
4845        return arg.multiplyBy(Fixnum.ZERO);
4846      }
4847    };
4848
4849  // ### integer-length
4850  private static final Primitive INTEGER_LENGTH =
4851    new Primitive(Symbol.INTEGER_LENGTH, "integer")
4852    {
4853      @Override
4854      public LispObject execute(LispObject arg) throws ConditionThrowable
4855      {
4856        if (arg instanceof Fixnum)
4857          {
4858            int n = ((Fixnum)arg).value;
4859            if (n < 0)
4860              n = ~n;
4861            int count = 0;
4862            while (n > 0)
4863              {
4864                n = n >>> 1;
4865                ++count;
4866              }
4867            return Fixnum.getInstance(count);
4868          }
4869        if (arg instanceof Bignum)
4870          return Fixnum.getInstance(((Bignum)arg).value.bitLength());
4871        return type_error(arg, Symbol.INTEGER);
4872      }
4873    };
4874
4875  // ### gcd-2
4876  private static final Primitive GCD_2 =
4877    new Primitive("gcd-2", PACKAGE_SYS, false)
4878    {
4879      @Override
4880      public LispObject execute(LispObject first, LispObject second)
4881        throws ConditionThrowable
4882      {
4883        BigInteger n1, n2;
4884        if (first instanceof Fixnum)
4885          n1 = BigInteger.valueOf(((Fixnum)first).value);
4886        else if (first instanceof Bignum)
4887          n1 = ((Bignum)first).value;
4888        else
4889          return type_error(first, Symbol.INTEGER);
4890        if (second instanceof Fixnum)
4891          n2 = BigInteger.valueOf(((Fixnum)second).value);
4892        else if (second instanceof Bignum)
4893          n2 = ((Bignum)second).value;
4894        else
4895          return type_error(second, Symbol.INTEGER);
4896        return number(n1.gcd(n2));
4897      }
4898    };
4899
4900  // ### identity-hash-code
4901  private static final Primitive IDENTITY_HASH_CODE =
4902    new Primitive("identity-hash-code", PACKAGE_SYS, true)
4903    {
4904      @Override
4905      public LispObject execute(LispObject arg) throws ConditionThrowable
4906      {
4907        return Fixnum.getInstance(System.identityHashCode(arg));
4908      }
4909    };
4910
4911  // ### simple-vector-search pattern vector => position
4912  // Searches vector for pattern.
4913  private static final Primitive SIMPLE_VECTOR_SEARCH =
4914    new Primitive("simple-vector-search", PACKAGE_SYS, false)
4915    {
4916      @Override
4917      public LispObject execute(LispObject first, LispObject second)
4918        throws ConditionThrowable
4919      {
4920        AbstractVector v = checkVector(second);
4921        if (first.length() == 0)
4922          return Fixnum.ZERO;
4923        final int patternLength = first.length();
4924        final int limit = v.length() - patternLength;
4925        if (first instanceof AbstractVector)
4926          {
4927            AbstractVector pattern = (AbstractVector) first;
4928            LispObject element = pattern.AREF(0);
4929            for (int i = 0; i <= limit; i++)
4930              {
4931                if (v.AREF(i).eql(element))
4932                  {
4933                    // Found match for first element of pattern.
4934                    boolean match = true;
4935                    // We've already checked the first element.
4936                    int j = i + 1;
4937                    for (int k = 1; k < patternLength; k++)
4938                      {
4939                        if (v.AREF(j).eql(pattern.AREF(k)))
4940                          {
4941                            ++j;
4942                          }
4943                        else
4944                          {
4945                            match = false;
4946                            break;
4947                          }
4948                      }
4949                    if (match)
4950                      return Fixnum.getInstance(i);
4951                  }
4952              }
4953          }
4954        else
4955          {
4956            // Pattern is a list.
4957            LispObject element = first.car();
4958            for (int i = 0; i <= limit; i++)
4959              {
4960                if (v.AREF(i).eql(element))
4961                  {
4962                    // Found match for first element of pattern.
4963                    boolean match = true;
4964                    // We've already checked the first element.
4965                    int j = i + 1;
4966                    for (LispObject rest = first.cdr(); rest != NIL; rest = rest.cdr())
4967                      {
4968                        if (v.AREF(j).eql(rest.car()))
4969                          {
4970                            ++j;
4971                          }
4972                        else
4973                          {
4974                            match = false;
4975                            break;
4976                          }
4977                      }
4978                    if (match)
4979                      return Fixnum.getInstance(i);
4980                  }
4981              }
4982          }
4983        return NIL;
4984      }
4985    };
4986
4987  // ### uptime
4988  private static final Primitive UPTIME =
4989    new Primitive("uptime", PACKAGE_EXT, true)
4990    {
4991      @Override
4992      public LispObject execute() throws ConditionThrowable
4993      {
4994        return number(System.currentTimeMillis() - Main.startTimeMillis);
4995      }
4996    };
4997
4998  // ### built-in-function-p
4999  private static final Primitive BUILT_IN_FUNCTION_P =
5000    new Primitive("built-in-function-p", PACKAGE_SYS, true)
5001    {
5002      @Override
5003      public LispObject execute(LispObject arg) throws ConditionThrowable
5004      {
5005            return checkSymbol(arg).isBuiltInFunction() ? T : NIL;
5006      }
5007    };
5008
5009  // ### inspected-parts
5010  private static final Primitive INSPECTED_PARTS =
5011    new Primitive("inspected-parts", PACKAGE_SYS, true)
5012    {
5013      @Override
5014      public LispObject execute(LispObject arg) throws ConditionThrowable
5015      {
5016        return arg.getParts();
5017      }
5018    };
5019
5020  // ### inspected-description
5021  private static final Primitive INSPECTED_DESCRIPTION =
5022    new Primitive("inspected-description", PACKAGE_SYS, false)
5023    {
5024      @Override
5025      public LispObject execute(LispObject arg) throws ConditionThrowable
5026      {
5027        return arg.getDescription();
5028      }
5029    };
5030
5031  // ### symbol-name
5032  public static final Primitive SYMBOL_NAME =
5033    new Primitive(Symbol.SYMBOL_NAME, "symbol")
5034    {
5035      @Override
5036      public LispObject execute(LispObject arg) throws ConditionThrowable
5037      {
5038          return checkSymbol(arg).name;
5039      }
5040    };
5041
5042  // ### symbol-package
5043  public static final Primitive SYMBOL_PACKAGE =
5044    new Primitive(Symbol.SYMBOL_PACKAGE, "symbol")
5045    {
5046      @Override
5047      public LispObject execute(LispObject arg) throws ConditionThrowable
5048      {
5049          return checkSymbol(arg).getPackage();
5050      }
5051    };
5052
5053  // ### symbol-function
5054  public static final Primitive SYMBOL_FUNCTION =
5055    new Primitive(Symbol.SYMBOL_FUNCTION, "symbol")
5056    {
5057      @Override
5058      public LispObject execute(LispObject arg) throws ConditionThrowable
5059      {
5060            LispObject function = checkSymbol(arg).getSymbolFunction();
5061            if (function != null)
5062              return function;
5063            return error(new UndefinedFunction(arg));
5064
5065      }
5066    };
5067
5068  // ### %set-symbol-function
5069  public static final Primitive _SET_SYMBOL_FUNCTION =
5070    new Primitive("%set-symbol-function", PACKAGE_SYS, false, "symbol function")
5071    {
5072      @Override
5073      public LispObject execute(LispObject first, LispObject second)
5074        throws ConditionThrowable
5075      {
5076            checkSymbol(first).setSymbolFunction(second);
5077            return second;
5078      }
5079    };
5080
5081  // ### symbol-plist
5082  public static final Primitive SYMBOL_PLIST =
5083    new Primitive(Symbol.SYMBOL_PLIST, "symbol")
5084    {
5085      @Override
5086      public LispObject execute(LispObject arg) throws ConditionThrowable
5087      {
5088            return checkSymbol(arg).getPropertyList();
5089      }
5090    };
5091
5092  // ### keywordp
5093  public static final Primitive KEYWORDP =
5094    new Primitive(Symbol.KEYWORDP, "object")
5095    {
5096      @Override
5097      public LispObject execute(LispObject arg) throws ConditionThrowable
5098      {
5099        if (arg instanceof Symbol)
5100          {
5101            if (checkSymbol(arg).getPackage() == PACKAGE_KEYWORD)
5102              return T;
5103          }
5104        return NIL;
5105      }
5106    };
5107
5108  // ### make-symbol
5109  public static final Primitive MAKE_SYMBOL =
5110    new Primitive(Symbol.MAKE_SYMBOL, "name")
5111    {
5112      @Override
5113      public LispObject execute(LispObject arg) throws ConditionThrowable
5114      {
5115        if (arg instanceof SimpleString)
5116          return new Symbol((SimpleString)arg);
5117        // Not a simple string.
5118        if (arg instanceof AbstractString)
5119          return new Symbol(arg.getStringValue());
5120        return type_error(arg, Symbol.STRING);
5121      }
5122    };
5123
5124  // ### makunbound
5125  public static final Primitive MAKUNBOUND =
5126    new Primitive(Symbol.MAKUNBOUND, "symbol")
5127    {
5128      @Override
5129      public LispObject execute(LispObject arg) throws ConditionThrowable
5130      {
5131            checkSymbol(arg).setSymbolValue(null);
5132            return arg;
5133      }
5134    };
5135
5136  // ### %class-name
5137  private static final Primitive _CLASS_NAME =
5138    new Primitive("%class-name", PACKAGE_SYS, true, "class")
5139    {
5140      @Override
5141      public LispObject execute(LispObject arg) throws ConditionThrowable
5142      {
5143          return checkClass(arg).symbol;
5144      }
5145    };
5146
5147  // ### %set-class-name
5148  private static final Primitive _SET_CLASS_NAME =
5149    new Primitive("%set-class-name", PACKAGE_SYS, true)
5150    {
5151      @Override
5152      public LispObject execute(LispObject first, LispObject second)
5153        throws ConditionThrowable
5154      {
5155          checkClass(first).symbol = checkSymbol(second);
5156          return second;
5157      }
5158    };
5159
5160  // ### class-layout
5161  private static final Primitive CLASS_LAYOUT =
5162    new Primitive("class-layout", PACKAGE_SYS, true, "class")
5163    {
5164      @Override
5165      public LispObject execute(LispObject arg) throws ConditionThrowable
5166      {
5167          Layout layout = checkClass(arg).getClassLayout();
5168          return layout != null ? layout : NIL;
5169      }
5170    };
5171
5172  // ### %set-class-layout
5173  private static final Primitive _SET_CLASS_LAYOUT =
5174    new Primitive("%set-class-layout", PACKAGE_SYS, true, "class layout")
5175    {
5176      @Override
5177      public LispObject execute(LispObject first, LispObject second)
5178        throws ConditionThrowable
5179      {
5180        if (second instanceof Layout)
5181          {
5182            checkClass(first).setClassLayout((Layout)second);
5183            return second;
5184          }
5185        return type_error(second, Symbol.LAYOUT);
5186      }
5187    };
5188
5189  // ### class-direct-superclasses
5190  private static final Primitive CLASS_DIRECT_SUPERCLASSES =
5191    new Primitive("class-direct-superclasses", PACKAGE_SYS, true)
5192    {
5193      @Override
5194      public LispObject execute(LispObject arg) throws ConditionThrowable
5195      {
5196            return checkClass(arg).getDirectSuperclasses();
5197      }
5198    };
5199
5200  // ### %set-class-direct-superclasses
5201  private static final Primitive _SET_CLASS_DIRECT_SUPERCLASSES =
5202    new Primitive("%set-class-direct-superclasses", PACKAGE_SYS, true)
5203    {
5204      @Override
5205      public LispObject execute(LispObject first, LispObject second)
5206        throws ConditionThrowable
5207      {
5208            checkClass(first).setDirectSuperclasses(second);
5209            return second;
5210      }
5211    };
5212
5213  // ### class-direct-subclasses
5214  private static final Primitive CLASS_DIRECT_SUBCLASSES =
5215    new Primitive("class-direct-subclasses", PACKAGE_SYS, true)
5216    {
5217      @Override
5218      public LispObject execute(LispObject arg) throws ConditionThrowable
5219      {
5220            return checkClass(arg).getDirectSubclasses();
5221      }
5222    };
5223
5224  // ### %set-class-direct-subclasses
5225  private static final Primitive _SET_CLASS_DIRECT_SUBCLASSES =
5226    new Primitive("%set-class-direct-subclasses", PACKAGE_SYS, true,
5227                  "class direct-subclasses")
5228    {
5229      @Override
5230      public LispObject execute(LispObject first, LispObject second)
5231        throws ConditionThrowable
5232      {
5233          checkClass(first).setDirectSubclasses(second);
5234          return second;
5235      }
5236    };
5237
5238  // ### %class-precedence-list
5239  private static final Primitive _CLASS_PRECEDENCE_LIST =
5240    new Primitive("%class-precedence-list", PACKAGE_SYS, true)
5241    {
5242      @Override
5243      public LispObject execute(LispObject arg) throws ConditionThrowable
5244      {
5245          return checkClass(arg).getCPL();
5246      }
5247    };
5248
5249  // ### set-class-precedence-list
5250  private static final Primitive SET_CLASS_PRECEDENCE_LIST =
5251    new Primitive("set-class-precedence-list", PACKAGE_SYS, true)
5252    {
5253      @Override
5254      public LispObject execute(LispObject first, LispObject second)
5255        throws ConditionThrowable
5256      {
5257          checkClass(first).classPrecedenceList = second;
5258          return second;
5259      }
5260    };
5261
5262  // ### class-direct-methods
5263  private static final Primitive CLASS_DIRECT_METHODS =
5264    new Primitive("class-direct-methods", PACKAGE_SYS, true)
5265    {
5266      @Override
5267      public LispObject execute(LispObject arg)
5268        throws ConditionThrowable
5269      {
5270          return checkClass(arg).directMethods;
5271      }
5272    };
5273
5274  // ### %set-class-direct-methods
5275  private static final Primitive _SET_CLASS_DIRECT_METHODS =
5276    new Primitive("%set-class-direct-methods", PACKAGE_SYS, true)
5277    {
5278      @Override
5279      public LispObject execute(LispObject first, LispObject second)
5280        throws ConditionThrowable
5281      {
5282          checkClass(first).directMethods = second;
5283          return second;
5284      }
5285    };
5286
5287  // ### class-documentation
5288  private static final Primitive CLASS_DOCUMENTATION =
5289    new Primitive("class-documentation", PACKAGE_SYS, true)
5290    {
5291      @Override
5292      public LispObject execute(LispObject arg)
5293        throws ConditionThrowable
5294      {
5295          return checkClass(arg).documentation;
5296      }
5297    };
5298
5299  // ### %set-class-documentation
5300  private static final Primitive _SET_CLASS_DOCUMENTATION =
5301    new Primitive("%set-class-documentation", PACKAGE_SYS, true)
5302    {
5303      @Override
5304      public LispObject execute(LispObject first, LispObject second)
5305        throws ConditionThrowable
5306      {
5307          checkClass(first).documentation = second;
5308          return second;
5309      }
5310    };
5311
5312  // ### class-finalized-p
5313  private static final Primitive CLASS_FINALIZED_P =
5314    new Primitive("class-finalized-p", PACKAGE_SYS, true)
5315    {
5316      @Override
5317      public LispObject execute(LispObject arg) throws ConditionThrowable
5318      {
5319            return checkClass(arg).isFinalized() ? T : NIL;
5320      }
5321    };
5322
5323  // ### %set-class-finalized-p
5324  private static final Primitive _SET_CLASS_FINALIZED_P =
5325    new Primitive("%set-class-finalized-p", PACKAGE_SYS, true)
5326    {
5327      @Override
5328      public LispObject execute(LispObject first, LispObject second)
5329        throws ConditionThrowable
5330      {
5331          checkClass(first).setFinalized(second != NIL);
5332          return second;
5333      }
5334    };
5335
5336  // ### classp
5337  private static final Primitive CLASSP =
5338    new Primitive("classp", PACKAGE_EXT, true)
5339    {
5340      @Override
5341      public LispObject execute(LispObject arg)
5342      {
5343        return arg instanceof LispClass ? T : NIL;
5344      }
5345    };
5346
5347  // ### char-to-utf8 char => octets
5348  private static final Primitive CHAR_TO_UTF8 =
5349    new Primitive("char-to-utf8", PACKAGE_EXT, true)
5350    {
5351      @Override
5352      public LispObject execute(LispObject arg) throws ConditionThrowable
5353      {
5354        final LispCharacter c;
5355        c = checkCharacter( arg);
5356        char[] chars = new char[1];
5357        chars[0] = c.value;
5358        String s = new String(chars);
5359        final byte[] bytes;
5360        try
5361          {
5362            bytes = s.getBytes("UTF8");
5363          }
5364        catch (java.io.UnsupportedEncodingException e)
5365          {
5366            return error(new LispError("UTF8 is not a supported encoding."));
5367          }
5368        LispObject[] objects = new LispObject[bytes.length];
5369        for (int i = bytes.length; i-- > 0;)
5370          {
5371            int n = bytes[i];
5372            if (n < 0)
5373              n += 256;
5374            objects[i] = Fixnum.getInstance(n);
5375          }
5376        return new SimpleVector(objects);
5377      }
5378    };
5379
5380  // ### %documentation
5381  private static final Primitive _DOCUMENTATION =
5382    new Primitive("%documentation", PACKAGE_SYS, true,
5383                  "object doc-type")
5384    {
5385      @Override
5386      public LispObject execute(LispObject object, LispObject docType)
5387        throws ConditionThrowable
5388      {
5389        LispObject doc = object.getDocumentation(docType);
5390        if (doc == NIL)
5391          {
5392            if (docType == Symbol.FUNCTION && object instanceof Symbol)
5393              {
5394                LispObject function = object.getSymbolFunction();
5395                if (function != null)
5396                  doc = function.getDocumentation(docType);
5397              }
5398          }
5399        return doc;
5400      }
5401    };
5402
5403  // ### %set-documentation
5404  private static final Primitive _SET_DOCUMENTATION =
5405    new Primitive("%set-documentation", PACKAGE_SYS, true,
5406                  "object doc-type documentation")
5407    {
5408      @Override
5409      public LispObject execute(LispObject object, LispObject docType,
5410                                LispObject documentation)
5411        throws ConditionThrowable
5412      {
5413        object.setDocumentation(docType, documentation);
5414        return documentation;
5415      }
5416    };
5417
5418  // ### %putf
5419  private static final Primitive _PUTF =
5420    new Primitive("%putf", PACKAGE_SYS, true,
5421                  "plist indicator new-value")
5422    {
5423      @Override
5424      public LispObject execute(LispObject plist, LispObject indicator,
5425                                LispObject newValue)
5426        throws ConditionThrowable
5427      {
5428        return putf(plist, indicator, newValue);
5429      }
5430    };
5431
5432  // ### function-plist
5433  private static final Primitive FUNCTION_PLIST =
5434    new Primitive("function-plist", PACKAGE_SYS, true, "function")
5435    {
5436      @Override
5437      public LispObject execute(LispObject arg) throws ConditionThrowable
5438      {
5439          return checkFunction(arg).getPropertyList();
5440      }
5441    };
5442
5443  // ### make-keyword
5444  private static final Primitive MAKE_KEYWORD =
5445    new Primitive("make-keyword", PACKAGE_SYS, true, "symbol")
5446    {
5447      @Override
5448      public LispObject execute(LispObject arg) throws ConditionThrowable
5449      {
5450          return PACKAGE_KEYWORD.intern(checkSymbol(arg).name);
5451      }
5452    };
5453
5454  // ### standard-object-p object => generalized-boolean
5455  private static final Primitive STANDARD_OBJECT_P =
5456    new Primitive("standard-object-p", PACKAGE_SYS, true, "object")
5457    {
5458      @Override
5459      public LispObject execute(LispObject arg)
5460      {
5461        return arg instanceof StandardObject ? T : NIL;
5462      }
5463    };
5464
5465  // ### copy-tree
5466  private static final Primitive COPY_TREE =
5467    new Primitive(Symbol.COPY_TREE, "object")
5468    {
5469      @Override
5470      public LispObject execute(LispObject arg)
5471      {
5472        if (arg instanceof Cons)
5473          {
5474            Cons cons = (Cons) arg;
5475            return new Cons(execute(cons.car), execute(cons.cdr));
5476          }
5477        else
5478          return arg;
5479      }
5480    };
5481   
5482}
Note: See TracBrowser for help on using the repository browser.