source: branches/0.22.x/abcl/src/org/armedbear/lisp/StandardGenericFunction.java

Last change on this file was 12898, checked in by Mark Evenson, 14 years ago

Fix documentation typo.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 25.5 KB
Line 
1/*
2 * StandardGenericFunction.java
3 *
4 * Copyright (C) 2003-2006 Peter Graves
5 * $Id: StandardGenericFunction.java 12898 2010-08-15 17:24:48Z mevenson $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 * 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 static org.armedbear.lisp.Lisp.*;
37
38import java.util.HashMap;
39
40public final class StandardGenericFunction extends StandardObject
41{
42  LispObject function;
43
44  int numberOfRequiredArgs;
45
46  HashMap<CacheEntry,LispObject> cache;
47  HashMap<LispObject,LispObject> slotCache;
48
49  public StandardGenericFunction()
50  {
51    super(StandardClass.STANDARD_GENERIC_FUNCTION,
52          StandardClass.STANDARD_GENERIC_FUNCTION.getClassLayout().getLength());
53  }
54
55  public StandardGenericFunction(String name, Package pkg, boolean exported,
56                                 Function function, LispObject lambdaList,
57                                 LispObject specializers)
58  {
59    this();
60    Symbol symbol;
61    if (exported)
62      symbol = pkg.internAndExport(name.toUpperCase());
63    else
64      symbol = pkg.intern(name.toUpperCase());
65    symbol.setSymbolFunction(this);
66    this.function = function;
67    slots[StandardGenericFunctionClass.SLOT_INDEX_NAME] = symbol;
68    slots[StandardGenericFunctionClass.SLOT_INDEX_LAMBDA_LIST] =
69      lambdaList;
70    slots[StandardGenericFunctionClass.SLOT_INDEX_REQUIRED_ARGS] =
71      lambdaList;
72    numberOfRequiredArgs = lambdaList.length();
73    slots[StandardGenericFunctionClass.SLOT_INDEX_INITIAL_METHODS] =
74      NIL;
75    StandardMethod method =
76      new StandardMethod(this, function, lambdaList, specializers);
77    slots[StandardGenericFunctionClass.SLOT_INDEX_METHODS] =
78      list(method);
79    slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_CLASS] =
80      StandardClass.STANDARD_METHOD;
81    slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_COMBINATION] =
82      Symbol.STANDARD;
83    slots[StandardGenericFunctionClass.SLOT_INDEX_ARGUMENT_PRECEDENCE_ORDER] =
84      NIL;
85    slots[StandardGenericFunctionClass.SLOT_INDEX_CLASSES_TO_EMF_TABLE] =
86      NIL;
87    slots[StandardGenericFunctionClass.SLOT_INDEX_DOCUMENTATION] = NIL;
88  }
89
90  void finalizeInternal()
91  {
92    cache = null;
93  }
94
95  @Override
96  public LispObject typep(LispObject type)
97  {
98    if (type == Symbol.COMPILED_FUNCTION)
99      {
100        if (function != null)
101          return function.typep(type);
102        else
103          return NIL;
104      }
105    if (type == Symbol.STANDARD_GENERIC_FUNCTION)
106      return T;
107    if (type == StandardClass.STANDARD_GENERIC_FUNCTION)
108      return T;
109    return super.typep(type);
110  }
111
112  public LispObject getGenericFunctionName()
113  {
114    return slots[StandardGenericFunctionClass.SLOT_INDEX_NAME];
115  }
116
117  public void setGenericFunctionName(LispObject name)
118  {
119    slots[StandardGenericFunctionClass.SLOT_INDEX_NAME] = name;
120  }
121
122  @Override
123  public LispObject execute()
124  {
125    return function.execute();
126  }
127
128  @Override
129  public LispObject execute(LispObject arg)
130  {
131    return function.execute(arg);
132  }
133
134  @Override
135  public LispObject execute(LispObject first, LispObject second)
136
137  {
138    return function.execute(first, second);
139  }
140
141  @Override
142  public LispObject execute(LispObject first, LispObject second,
143                            LispObject third)
144
145  {
146    return function.execute(first, second, third);
147  }
148
149  @Override
150  public LispObject execute(LispObject first, LispObject second,
151                            LispObject third, LispObject fourth)
152
153  {
154    return function.execute(first, second, third, fourth);
155  }
156
157  @Override
158  public LispObject execute(LispObject first, LispObject second,
159                            LispObject third, LispObject fourth,
160                            LispObject fifth)
161
162  {
163    return function.execute(first, second, third, fourth,
164                            fifth);
165  }
166
167  @Override
168  public LispObject execute(LispObject first, LispObject second,
169                            LispObject third, LispObject fourth,
170                            LispObject fifth, LispObject sixth)
171
172  {
173    return function.execute(first, second, third, fourth,
174                            fifth, sixth);
175  }
176
177  @Override
178  public LispObject execute(LispObject first, LispObject second,
179                            LispObject third, LispObject fourth,
180                            LispObject fifth, LispObject sixth,
181                            LispObject seventh)
182
183  {
184    return function.execute(first, second, third, fourth,
185                            fifth, sixth, seventh);
186  }
187
188  @Override
189  public LispObject execute(LispObject first, LispObject second,
190                            LispObject third, LispObject fourth,
191                            LispObject fifth, LispObject sixth,
192                            LispObject seventh, LispObject eighth)
193
194  {
195    return function.execute(first, second, third, fourth,
196                            fifth, sixth, seventh, eighth);
197  }
198
199  @Override
200  public LispObject execute(LispObject[] args)
201  {
202    return function.execute(args);
203  }
204
205  @Override
206  public String writeToString()
207  {
208    LispObject name = getGenericFunctionName();
209    if (name != null)
210      {
211        StringBuilder sb = new StringBuilder();
212        LispObject className;
213        LispObject lispClass = getLispClass();
214        if (lispClass instanceof LispClass)
215          className = ((LispClass)lispClass).getName();
216        else
217          className = Symbol.CLASS_NAME.execute(lispClass);
218
219        sb.append(className.writeToString());
220        sb.append(' ');
221        sb.append(name.writeToString());
222        return unreadableString(sb.toString());
223      }
224    return super.writeToString();
225  }
226
227  // Profiling.
228  private int callCount;
229  private int hotCount;
230
231  @Override
232  public final int getCallCount()
233  {
234    return callCount;
235  }
236
237  @Override
238  public void setCallCount(int n)
239  {
240    callCount = n;
241  }
242
243  @Override
244  public final void incrementCallCount()
245  {
246    ++callCount;
247  }
248
249    @Override
250    public final int getHotCount()
251    {
252        return hotCount;
253    }
254
255    @Override
256    public void setHotCount(int n)
257    {
258        hotCount = n;
259    }
260
261    @Override
262    public final void incrementHotCount()
263    {
264        ++hotCount;
265    }
266
267    // AMOP (p. 216) specifies the following readers as generic functions:
268  //   generic-function-argument-precedence-order
269  //   generic-function-declarations
270  //   generic-function-lambda-list
271  //   generic-function-method-class
272  //   generic-function-method-combination
273  //   generic-function-methods
274  //   generic-function-name
275
276  // ### %generic-function-name
277  private static final Primitive _GENERIC_FUNCTION_NAME =
278    new Primitive("%generic-function-name", PACKAGE_SYS, true)
279    {
280      @Override
281      public LispObject execute(LispObject arg)
282      {
283          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_NAME];
284      }
285    };
286
287  // ### %set-generic-function-name
288  private static final Primitive _SET_GENERIC_FUNCTION_NAME =
289    new Primitive("%set-generic-function-name", PACKAGE_SYS, true)
290    {
291      @Override
292      public LispObject execute(LispObject first, LispObject second)
293
294      {
295          checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_NAME] = second;
296          return second;
297      }
298    };
299
300  // ### %generic-function-lambda-list
301  private static final Primitive _GENERIC_FUNCTION_LAMBDA_LIST =
302    new Primitive("%generic-function-lambda-list", PACKAGE_SYS, true)
303    {
304      @Override
305      public LispObject execute(LispObject arg)
306      {
307          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_LAMBDA_LIST];
308      }
309    };
310
311  // ### %set-generic-function-lambdaList
312  private static final Primitive _SET_GENERIC_FUNCTION_LAMBDA_LIST =
313    new Primitive("%set-generic-function-lambda-list", PACKAGE_SYS, true)
314    {
315      @Override
316      public LispObject execute(LispObject first, LispObject second)
317
318      {
319          checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_LAMBDA_LIST] = second;
320          return second;
321      }
322    };
323
324  // ### funcallable-instance-function funcallable-instance => function
325  private static final Primitive FUNCALLABLE_INSTANCE_FUNCTION =
326    new Primitive("funcallable-instance-function", PACKAGE_MOP, false,
327                  "funcallable-instance")
328    {
329      @Override
330      public LispObject execute(LispObject arg)
331
332      {
333          return checkStandardGenericFunction(arg).function;
334      }
335    };
336
337  // ### set-funcallable-instance-function funcallable-instance function => unspecified
338  // AMOP p. 230
339  private static final Primitive SET_FUNCALLABLE_INSTANCE_FUNCTION =
340    new Primitive("set-funcallable-instance-function", PACKAGE_MOP, true,
341                  "funcallable-instance function")
342    {
343      @Override
344      public LispObject execute(LispObject first, LispObject second)
345
346      {
347          checkStandardGenericFunction(first).function = second;
348          return second;
349      }
350    };
351
352  // ### gf-required-args
353  private static final Primitive GF_REQUIRED_ARGS =
354    new Primitive("gf-required-args", PACKAGE_SYS, true)
355    {
356      @Override
357      public LispObject execute(LispObject arg)
358      {
359          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_REQUIRED_ARGS];
360      }
361    };
362
363  // ### %set-gf-required-args
364  private static final Primitive _SET_GF_REQUIRED_ARGS =
365    new Primitive("%set-gf-required-args", PACKAGE_SYS, true)
366    {
367      @Override
368      public LispObject execute(LispObject first, LispObject second)
369
370      {
371        final StandardGenericFunction gf = checkStandardGenericFunction(first);
372        gf.slots[StandardGenericFunctionClass.SLOT_INDEX_REQUIRED_ARGS] = second;
373        gf.numberOfRequiredArgs = second.length();
374        return second;
375      }
376    };
377
378  // ### generic-function-initial-methods
379  private static final Primitive GENERIC_FUNCTION_INITIAL_METHODS =
380    new Primitive("generic-function-initial-methods", PACKAGE_SYS, true)
381    {
382      @Override
383      public LispObject execute(LispObject arg)
384      {
385          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_INITIAL_METHODS];
386      }
387    };
388
389  // ### set-generic-function-initial-methods
390  private static final Primitive SET_GENERIC_FUNCTION_INITIAL_METHODS =
391    new Primitive("set-generic-function-initial-methods", PACKAGE_SYS, true)
392    {
393      @Override
394      public LispObject execute(LispObject first, LispObject second)
395
396      {
397          checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_INITIAL_METHODS] = second;
398          return second;
399      }
400    };
401
402  // ### generic-function-methods
403  private static final Primitive GENERIC_FUNCTION_METHODS =
404    new Primitive("generic-function-methods", PACKAGE_SYS, true)
405    {
406      @Override
407      public LispObject execute(LispObject arg)
408      {
409          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_METHODS];
410      }
411    };
412
413  // ### set-generic-function-methods
414  private static final Primitive SET_GENERIC_FUNCTION_METHODS =
415    new Primitive("set-generic-function-methods", PACKAGE_SYS, true)
416    {
417      @Override
418      public LispObject execute(LispObject first, LispObject second)
419
420      {
421          checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_METHODS] = second;
422          return second;
423      }
424    };
425
426  // ### generic-function-method-class
427  private static final Primitive GENERIC_FUNCTION_METHOD_CLASS =
428    new Primitive("generic-function-method-class", PACKAGE_SYS, true)
429    {
430      @Override
431      public LispObject execute(LispObject arg)
432      {
433          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_CLASS];
434      }
435    };
436
437  // ### set-generic-function-method-class
438  private static final Primitive SET_GENERIC_FUNCTION_METHOD_CLASS =
439    new Primitive("set-generic-function-method-class", PACKAGE_SYS, true)
440    {
441      @Override
442      public LispObject execute(LispObject first, LispObject second)
443
444      {
445          checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_CLASS] = second;
446          return second;
447      }
448    };
449
450  // ### generic-function-method-combination
451  private static final Primitive GENERIC_FUNCTION_METHOD_COMBINATION =
452    new Primitive("generic-function-method-combination", PACKAGE_SYS, true)
453    {
454      @Override
455      public LispObject execute(LispObject arg)
456      {
457          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_COMBINATION];
458      }
459    };
460
461  // ### set-generic-function-method-combination
462  private static final Primitive SET_GENERIC_FUNCTION_METHOD_COMBINATION =
463    new Primitive("set-generic-function-method-combination", PACKAGE_SYS, true)
464    {
465      @Override
466      public LispObject execute(LispObject first, LispObject second)
467
468      {
469          checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_COMBINATION] 
470      = second;
471          return second;
472      }
473    };
474
475  // ### generic-function-argument-precedence-order
476  private static final Primitive GENERIC_FUNCTION_ARGUMENT_PRECEDENCE_ORDER =
477    new Primitive("generic-function-argument-precedence-order", PACKAGE_SYS, true)
478    {
479      @Override
480      public LispObject execute(LispObject arg)
481      {
482          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass
483               .SLOT_INDEX_ARGUMENT_PRECEDENCE_ORDER];
484      }
485    };
486
487  // ### set-generic-function-argument-precedence-order
488  private static final Primitive SET_GENERIC_FUNCTION_ARGUMENT_PRECEDENCE_ORDER =
489    new Primitive("set-generic-function-argument-precedence-order", PACKAGE_SYS, true)
490    {
491      @Override
492      public LispObject execute(LispObject first, LispObject second)
493
494      {
495          checkStandardGenericFunction(first)
496      .slots[StandardGenericFunctionClass.SLOT_INDEX_ARGUMENT_PRECEDENCE_ORDER] = second;
497          return second;
498      }
499    };
500
501  // ### generic-function-classes-to-emf-table
502  private static final Primitive GENERIC_FUNCTION_CLASSES_TO_EMF_TABLE =
503    new Primitive("generic-function-classes-to-emf-table", PACKAGE_SYS, true)
504    {
505      @Override
506      public LispObject execute(LispObject arg)
507      {
508          return checkStandardGenericFunction(arg)
509      .slots[StandardGenericFunctionClass.SLOT_INDEX_CLASSES_TO_EMF_TABLE];
510      }
511    };
512
513  // ### set-generic-function-classes-to-emf-table
514  private static final Primitive SET_GENERIC_FUNCTION_CLASSES_TO_EMF_TABLE =
515    new Primitive("set-generic-function-classes-to-emf-table", PACKAGE_SYS, true)
516    {
517      @Override
518      public LispObject execute(LispObject first, LispObject second)
519
520      {
521          checkStandardGenericFunction(first)
522      .slots[StandardGenericFunctionClass.SLOT_INDEX_CLASSES_TO_EMF_TABLE] = second;
523          return second;
524      }
525    };
526
527  // ### generic-function-documentation
528  private static final Primitive GENERIC_FUNCTION_DOCUMENTATION =
529    new Primitive("generic-function-documentation", PACKAGE_SYS, true)
530    {
531      @Override
532      public LispObject execute(LispObject arg)
533      {
534          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_DOCUMENTATION];
535      }
536    };
537
538  // ### set-generic-function-documentation
539  private static final Primitive SET_GENERIC_FUNCTION_DOCUMENTATION =
540    new Primitive("set-generic-function-documentation", PACKAGE_SYS, true)
541    {
542      @Override
543      public LispObject execute(LispObject first, LispObject second)
544
545      {
546          checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_DOCUMENTATION] 
547      = second;
548          return second;
549      }
550    };
551
552  // ### %finalize-generic-function
553  private static final Primitive _FINALIZE_GENERIC_FUNCTION =
554    new Primitive("%finalize-generic-function", PACKAGE_SYS, true,
555                  "generic-function")
556    {
557      @Override
558      public LispObject execute(LispObject arg)
559      {
560          final StandardGenericFunction gf = checkStandardGenericFunction(arg);
561          gf.finalizeInternal();       
562          return T;
563      }
564    };
565
566  // ### cache-emf
567  private static final Primitive CACHE_EMF =
568    new Primitive("cache-emf", PACKAGE_SYS, true, "generic-function args emf")
569    {
570      @Override
571      public LispObject execute(LispObject first, LispObject second,
572                                LispObject third)
573
574      {
575        final StandardGenericFunction gf = checkStandardGenericFunction(first);
576        LispObject args = second;
577        LispObject[] array = new LispObject[gf.numberOfRequiredArgs];
578        for (int i = gf.numberOfRequiredArgs; i-- > 0;)
579          {
580            array[i] = gf.getArgSpecialization(args.car());
581            args = args.cdr();
582          }
583        CacheEntry specializations = new CacheEntry(array);
584        HashMap<CacheEntry,LispObject> ht = gf.cache;
585        if (ht == null)
586            ht = gf.cache = new HashMap<CacheEntry,LispObject>();
587        ht.put(specializations, third);
588        return third;
589      }
590    };
591
592  // ### get-cached-emf
593  private static final Primitive GET_CACHED_EMF =
594    new Primitive("get-cached-emf", PACKAGE_SYS, true, "generic-function args")
595    {
596      @Override
597      public LispObject execute(LispObject first, LispObject second)
598
599      {
600        final StandardGenericFunction gf = checkStandardGenericFunction(first);
601        LispObject args = second;
602        LispObject[] array = new LispObject[gf.numberOfRequiredArgs];
603        for (int i = gf.numberOfRequiredArgs; i-- > 0;)
604          {
605            array[i] = gf.getArgSpecialization(args.car());
606            args = args.cdr();
607          }
608        CacheEntry specializations = new CacheEntry(array);
609        HashMap<CacheEntry,LispObject> ht = gf.cache;
610        if (ht == null)
611          return NIL;
612        LispObject emf = (LispObject) ht.get(specializations);
613        return emf != null ? emf : NIL;
614      }
615    };
616
617  /**
618   * Returns an object representing generic function
619   * argument <tt>arg</tt> in a <tt>CacheEntry</tt>
620   *
621   * <p>In the simplest case, when this generic function
622   * does not have EQL specialized methods, and therefore
623   * only argument types are relevant for choosing
624   * applicable methods, the value returned is the
625   * class of <tt>arg</tt>
626   *
627   * <p>If the function has EQL specialized methods:
628   *   - if <tt>arg</tt> is EQL to some of the EQL-specializers,
629   *     a special object representing equality to that specializer
630   *     is returned.
631   *   - otherwise class of the <tt>arg</tt> is returned.
632   *
633   * <p>Note that we do not consider argument position, when
634   * calculating arg specialization. In rare cases (when one argument
635   * is eql-specialized to a symbol specifying class of another
636   * argument) this may result in redundant cache entries caching the
637   * same method. But the method cached is anyway correct for the
638   * arguments (because in case of cache miss, correct method is
639   * calculated by other code, which does not rely on
640   * getArgSpecialization; and because EQL is true only for objects of
641   * the same type, which guaranties that if a type-specialized
642   * methods was chached by eql-specialization, all the cache hits
643   * into this records will be from args of the conforming type).
644   *
645   * <p>Consider:
646   * <pre><tt>
647   * (defgeneric f (a b))
648   *
649   * (defmethod f (a (b (eql 'symbol)))
650   *   "T (EQL 'SYMBOL)")
651   *
652   * (defmethod f ((a symbol) (b (eql 'symbol)))
653   *   "SYMBOL (EQL 'SYMBOL)")
654   *
655   * (f 12 'symbol)
656   * => "T (EQL 'SYMBOL)"
657   *
658   * (f 'twelve 'symbol)
659   * => "SYMBOL (EQL 'SYMBOL)"
660   *
661   * (f 'symbol 'symbol)
662   * => "SYMBOL (EQL 'SYMBOL)"
663   *
664   * </tt></pre>
665   *
666   * After the two above calls <tt>cache</tt> will contain three keys:
667   * <pre>
668   * { class FIXNUM, EqlSpecialization('SYMBOL) }
669   * { class SYMBOL, EqlSpecialization('SYMBOL) }
670   * { EqlSpecialization('SYMBOL), EqlSpecialization('SYMBOL) }.
671   * </pre>
672   */     
673  LispObject getArgSpecialization(LispObject arg)
674  {
675    for (EqlSpecialization eqlSpecialization : eqlSpecializations)
676      {
677        if (eqlSpecialization.eqlTo.eql(arg))
678          return eqlSpecialization;
679      }
680    return arg.classOf();
681  }
682
683  // ### %get-arg-specialization
684  private static final Primitive _GET_ARG_SPECIALIZATION =
685    new Primitive("%get-arg-specialization", PACKAGE_SYS, true, "generic-function arg")
686    {
687      @Override
688      public LispObject execute(LispObject first, LispObject second)
689
690      {
691        final StandardGenericFunction gf = checkStandardGenericFunction(first);
692        return gf.getArgSpecialization(second);
693      }
694    };
695
696  // ### cache-slot-location
697  private static final Primitive CACHE_SLOT_LOCATION =
698    new Primitive("cache-slot-location", PACKAGE_SYS, true, "generic-function layout location")
699    {
700      @Override
701      public LispObject execute(LispObject first, LispObject second,
702                                LispObject third)
703
704      {
705        final StandardGenericFunction gf = checkStandardGenericFunction(first);
706        LispObject layout = second;
707        LispObject location = third;
708        HashMap<LispObject,LispObject> ht = gf.slotCache;
709        if (ht == null)
710          ht = gf.slotCache = new HashMap<LispObject,LispObject>();
711        ht.put(layout, location);
712        return third;
713      }
714    };
715
716  // ### get-cached-slot-location
717  private static final Primitive GET_CACHED_SLOT_LOCATION =
718    new Primitive("get-cached-slot-location", PACKAGE_SYS, true, "generic-function layout")
719    {
720      @Override
721      public LispObject execute(LispObject first, LispObject second)
722
723      {
724        final StandardGenericFunction gf = checkStandardGenericFunction(first);
725        LispObject layout = second;
726        HashMap<LispObject,LispObject> ht = gf.slotCache;
727        if (ht == null)
728          return NIL;
729        LispObject location = (LispObject) ht.get(layout);
730        return location != null ? location : NIL;
731      }
732    };
733
734  private static final StandardGenericFunction GENERIC_FUNCTION_NAME =
735    new StandardGenericFunction("generic-function-name",
736                                PACKAGE_MOP,
737                                true,
738                                _GENERIC_FUNCTION_NAME,
739                                list(Symbol.GENERIC_FUNCTION),
740                                list(StandardClass.STANDARD_GENERIC_FUNCTION));
741
742  private static class CacheEntry
743  {
744    final LispObject[] array;
745
746    CacheEntry(LispObject[] array)
747    {
748      this.array = array;
749    }
750
751    @Override
752    public int hashCode()
753    {
754      int result = 0;
755      for (int i = array.length; i-- > 0;)
756        result ^= array[i].hashCode();
757      return result;
758    }
759
760    @Override
761    public boolean equals(Object object)
762    {
763      if (!(object instanceof CacheEntry))
764        return false;
765      final CacheEntry otherEntry = (CacheEntry) object;
766      if (otherEntry.array.length != array.length)
767        return false;
768      final LispObject[] otherArray = otherEntry.array;
769      for (int i = array.length; i-- > 0;)
770        if (array[i] != otherArray[i])
771          return false;
772      return true;
773    }
774  }
775
776  EqlSpecialization eqlSpecializations[] = new EqlSpecialization[0];
777
778    // ### %init-eql-specializations
779    private static final Primitive _INIT_EQL_SPECIALIZATIONS
780      = new Primitive("%init-eql-specializations", PACKAGE_SYS, true, 
781        "generic-function eql-specilizer-objects-list")
782      {
783        @Override
784        public LispObject execute(LispObject first, LispObject second)
785
786        {
787          final StandardGenericFunction gf = checkStandardGenericFunction(first);
788          LispObject eqlSpecializerObjects = second;
789          gf.eqlSpecializations = new EqlSpecialization[eqlSpecializerObjects.length()];
790          for (int i = 0; i < gf.eqlSpecializations.length; i++) {
791      gf.eqlSpecializations[i] = new EqlSpecialization(eqlSpecializerObjects.car());
792      eqlSpecializerObjects = eqlSpecializerObjects.cdr();
793          }
794          return NIL;
795        }
796      };
797
798  private static class EqlSpecialization extends LispObject
799  {
800    public LispObject eqlTo;
801
802    public EqlSpecialization(LispObject eqlTo)
803    {
804        this.eqlTo = eqlTo;
805    }
806  }
807 
808  public static final StandardGenericFunction checkStandardGenericFunction(LispObject obj)
809
810  {
811    if (obj instanceof StandardGenericFunction)
812      return (StandardGenericFunction) obj;
813    return (StandardGenericFunction) // Not reached.
814      type_error(obj, Symbol.STANDARD_GENERIC_FUNCTION);
815  }
816}
Note: See TracBrowser for help on using the repository browser.