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

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

Convert docstrings and primitives to standard conventions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 30.5 KB
Line 
1/*
2 * StandardGenericFunction.java
3 *
4 * Copyright (C) 2003-2006 Peter Graves
5 * $Id: StandardGenericFunction.java 13541 2011-08-27 23:23:24Z 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.concurrent.ConcurrentHashMap;
39
40public final class StandardGenericFunction extends StandardObject
41{
42  LispObject function;
43
44  int numberOfRequiredArgs;
45
46  ConcurrentHashMap<CacheEntry,LispObject> cache;
47  ConcurrentHashMap<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 printObject()
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.princToString());
220        sb.append(' ');
221        sb.append(name.princToString());
222        return unreadableString(sb.toString());
223      }
224    return super.printObject();
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  private static final Primitive _GENERIC_FUNCTION_NAME
277    = new pf__generic_function_name();
278  @DocString(name="%generic-function-name")
279  private static final class pf__generic_function_name extends Primitive
280  {
281    pf__generic_function_name() 
282    {
283      super("%generic-function-name", PACKAGE_SYS, true);
284    }
285    @Override
286    public LispObject execute(LispObject arg)
287    {
288      return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_NAME];
289    }
290  };
291
292  private static final Primitive _SET_GENERIC_FUNCTION_NAME
293    = new pf__set_generic_function_name();
294  @DocString(name="%set-generic-function-name")
295  private static final class pf__set_generic_function_name extends Primitive
296  { 
297    pf__set_generic_function_name() 
298    {
299      super ("%set-generic-function-name", PACKAGE_SYS, true);
300    }
301    @Override
302    public LispObject execute(LispObject first, LispObject second)
303    {
304      checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_NAME] = second;
305      return second;
306    }
307  };
308
309  private static final Primitive _GENERIC_FUNCTION_LAMBDA_LIST
310    = new pf__generic_function_lambda_list();
311  @DocString(name ="%generic-function-lambda-list")
312  private static final class pf__generic_function_lambda_list extends Primitive {
313    pf__generic_function_lambda_list() 
314    {
315      super("%generic-function-lambda-list", PACKAGE_SYS, true);
316    }
317    @Override
318    public LispObject execute(LispObject arg)
319    {
320      return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_LAMBDA_LIST];
321    }
322  };
323
324  private static final Primitive _SET_GENERIC_FUNCTION_LAMBDA_LIST
325    = new pf__set_generic_function_lambda_list();
326  @DocString(name="%set-generic-function-lambdalist")
327  private static final class pf__set_generic_function_lambda_list extends Primitive
328  {
329    pf__set_generic_function_lambda_list()
330    {
331      super("%set-generic-function-lambda-list", PACKAGE_SYS, true);
332    }
333    @Override
334    public LispObject execute(LispObject first, LispObject second)
335    {
336      checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_LAMBDA_LIST] = second;
337      return second;
338    }
339  };
340
341  private static final Primitive FUNCALLABLE_INSTANCE_FUNCTION
342    = new pf_funcallable_instance_function();
343  @DocString(name="funcallable-instance-function",
344             args="funcallable-instance",
345             returns="function")
346  private static final class pf_funcallable_instance_function extends Primitive
347  {
348    pf_funcallable_instance_function()
349    {
350      super("funcallable-instance-function", PACKAGE_MOP, false,
351            "funcallable-instance");
352    }
353    @Override
354    public LispObject execute(LispObject arg)
355    {
356      return checkStandardGenericFunction(arg).function;
357    }
358  };
359
360  // AMOP p. 230
361  private static final Primitive SET_FUNCALLABLE_INSTANCE_FUNCTION
362    = new pf_set_funcallable_instance_function();
363  @DocString(name="set-funcallable-instance-function",
364             args="funcallable-instance function",
365             returns="unspecified")
366  private static final class pf_set_funcallable_instance_function extends Primitive
367  {
368    pf_set_funcallable_instance_function()
369    {
370      super("set-funcallable-instance-function", PACKAGE_MOP, true,
371            "funcallable-instance function");
372    }
373    @Override
374    public LispObject execute(LispObject first, LispObject second)
375    {
376      checkStandardGenericFunction(first).function = second;
377      return second;
378    }
379  };
380
381  private static final Primitive GF_REQUIRED_ARGS
382    = new pf_gf_required_args();
383  @DocString(name="gf-required-args")
384  private static final class pf_gf_required_args extends Primitive
385  {
386    pf_gf_required_args()
387    {
388      super("gf-required-args", PACKAGE_SYS, true);
389    }
390    @Override
391    public LispObject execute(LispObject arg)
392    {
393      return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_REQUIRED_ARGS];
394    }
395  };
396
397  private static final Primitive _SET_GF_REQUIRED_ARGS
398    = new pf__set_gf_required_args();
399  @DocString(name="%set-gf-required-args")
400  private static final class pf__set_gf_required_args extends Primitive
401  {
402    pf__set_gf_required_args()
403    {
404      super("%set-gf-required-args", PACKAGE_SYS, true);
405    }
406    @Override
407    public LispObject execute(LispObject first, LispObject second)
408    {
409      final StandardGenericFunction gf = checkStandardGenericFunction(first);
410      gf.slots[StandardGenericFunctionClass.SLOT_INDEX_REQUIRED_ARGS] = second;
411      gf.numberOfRequiredArgs = second.length();
412      return second;
413    }
414  };
415
416  private static final Primitive GENERIC_FUNCTION_INITIAL_METHODS
417    = new pf_generic_function_initial_methods();
418  @DocString(name="generic-function-initial-methods")
419  private static final class pf_generic_function_initial_methods extends Primitive
420  {
421    pf_generic_function_initial_methods() 
422    {
423      super("generic-function-initial-methods", PACKAGE_SYS, true);
424    }
425    @Override
426    public LispObject execute(LispObject arg)
427    {
428      return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_INITIAL_METHODS];
429    }
430  };
431
432  private static final Primitive SET_GENERIC_FUNCTION_INITIAL_METHODS
433    = new pf_set_generic_function_initial_methods();
434  @DocString(name="set-generic-function-initial-methods")
435  private static final class pf_set_generic_function_initial_methods extends Primitive
436  {
437    pf_set_generic_function_initial_methods()
438    {
439      super("set-generic-function-initial-methods", PACKAGE_SYS, true);
440    }
441    @Override
442    public LispObject execute(LispObject first, LispObject second)
443    {
444      checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_INITIAL_METHODS] = second;
445      return second;
446    }
447  };
448
449  private static final Primitive GENERIC_FUNCTION_METHODS
450    = new pf_generic_function_methods();
451  @DocString(name="generic-function-methods")
452  private static final class pf_generic_function_methods extends Primitive
453  {
454    pf_generic_function_methods()
455    {
456      super("generic-function-methods", PACKAGE_SYS, true);
457    }
458    @Override
459    public LispObject execute(LispObject arg)
460    {
461      return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_METHODS];
462    }
463  };
464
465  private static final Primitive SET_GENERIC_FUNCTION_METHODS
466    = new pf_set_generic_function_methods();
467  @DocString(name="set-generic-function-methods")
468  private static final class pf_set_generic_function_methods extends Primitive
469  {
470    pf_set_generic_function_methods()
471    {
472      super("set-generic-function-methods", PACKAGE_SYS, true);
473    }
474    @Override
475    public LispObject execute(LispObject first, LispObject second)
476    {
477      checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_METHODS] = second;
478      return second;
479    }
480  };
481
482  private static final Primitive GENERIC_FUNCTION_METHOD_CLASS
483    = new pf_generic_function_method_class();
484  @DocString(name="generic-function-method-class")
485  private static final class pf_generic_function_method_class extends Primitive
486  {
487    pf_generic_function_method_class()
488    {
489      super("generic-function-method-class", PACKAGE_SYS, true);
490    }
491    @Override
492    public LispObject execute(LispObject arg)
493    {
494      return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_CLASS];
495    }
496  };
497
498  private static final Primitive SET_GENERIC_FUNCTION_METHOD_CLASS
499    = new pf_set_generic_function_method_class();
500  @DocString(name="set-generic-function-method-class")
501  private static final class pf_set_generic_function_method_class extends Primitive
502  {
503    pf_set_generic_function_method_class()
504    {
505      super("set-generic-function-method-class", PACKAGE_SYS, true);
506    }
507    @Override
508    public LispObject execute(LispObject first, LispObject second)
509    {
510      checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_CLASS] = second;
511      return second;
512    }
513  };
514
515  private static final Primitive GENERIC_FUNCTION_METHOD_COMBINATION
516    = new pf_generic_function_method_combination(); 
517  @DocString(name="generic-function-method-combination")
518  private static final class pf_generic_function_method_combination extends Primitive
519  {
520    pf_generic_function_method_combination()
521    {
522      super("generic-function-method-combination", PACKAGE_SYS, true);
523    }
524    @Override
525    public LispObject execute(LispObject arg)
526    {
527      return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_COMBINATION];
528    }
529  };
530
531  private static final Primitive SET_GENERIC_FUNCTION_METHOD_COMBINATION
532    = new pf_set_generic_function_method_combination(); 
533  @DocString(name="set-generic-function-method-combination")
534  private static final class pf_set_generic_function_method_combination extends Primitive
535  {
536    pf_set_generic_function_method_combination()
537    {
538      super("set-generic-function-method-combination", PACKAGE_SYS, true);
539    }
540    @Override
541    public LispObject execute(LispObject first, LispObject second)
542    {
543      checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_COMBINATION] 
544        = second;
545      return second;
546    }
547  };
548
549  private static final Primitive GENERIC_FUNCTION_ARGUMENT_PRECEDENCE_ORDER
550    = new pf_generic_function_argument_precedence_order();
551  @DocString(name="generic-function-argument-precedence-order")
552  private static final class pf_generic_function_argument_precedence_order extends Primitive
553  {
554    pf_generic_function_argument_precedence_order()
555    { 
556      super("generic-function-argument-precedence-order", PACKAGE_SYS, true);
557    }
558    @Override
559    public LispObject execute(LispObject arg)
560    {
561      return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass
562                                                     .SLOT_INDEX_ARGUMENT_PRECEDENCE_ORDER];
563    }
564  };
565
566  private static final Primitive SET_GENERIC_FUNCTION_ARGUMENT_PRECEDENCE_ORDER
567    = new pf_set_generic_function_argument_precedence_order();
568  @DocString(name="set-generic-function-argument-precedence-order")
569  private static final class pf_set_generic_function_argument_precedence_order extends Primitive
570  {
571    pf_set_generic_function_argument_precedence_order()
572    {
573      super("set-generic-function-argument-precedence-order", PACKAGE_SYS, true);
574    }
575    @Override
576    public LispObject execute(LispObject first, LispObject second)
577    {
578      checkStandardGenericFunction(first)
579        .slots[StandardGenericFunctionClass.SLOT_INDEX_ARGUMENT_PRECEDENCE_ORDER] = second;
580      return second;
581    }
582  };
583
584  private static final Primitive GENERIC_FUNCTION_CLASSES_TO_EMF_TABLE
585    = new pf_generic_function_classes_to_emf_table();
586  @DocString(name="generic-function-classes-to-emf-table")
587  private static final class pf_generic_function_classes_to_emf_table extends Primitive
588  {
589    pf_generic_function_classes_to_emf_table() 
590    {
591      super("generic-function-classes-to-emf-table", PACKAGE_SYS, true);
592    }
593    @Override
594    public LispObject execute(LispObject arg)
595    {
596      return checkStandardGenericFunction(arg)
597        .slots[StandardGenericFunctionClass.SLOT_INDEX_CLASSES_TO_EMF_TABLE];
598    }
599  };
600
601  private static final Primitive SET_GENERIC_FUNCTION_CLASSES_TO_EMF_TABLE
602    = new pf_set_generic_function_classes_to_emf_table();
603  @DocString(name="set-generic-function-classes-to-emf-table")
604  private static final class pf_set_generic_function_classes_to_emf_table extends Primitive
605  {
606    pf_set_generic_function_classes_to_emf_table()
607    {
608      super("set-generic-function-classes-to-emf-table", PACKAGE_SYS, true);
609    }
610    @Override
611    public LispObject execute(LispObject first, LispObject second)
612    {
613      checkStandardGenericFunction(first)
614        .slots[StandardGenericFunctionClass.SLOT_INDEX_CLASSES_TO_EMF_TABLE] = second;
615      return second;
616    }
617  };
618
619  private static final Primitive GENERIC_FUNCTION_DOCUMENTATION
620    = new pf_generic_function_documentation();
621  @DocString(name="generic-function-documentation")
622  private static final class pf_generic_function_documentation extends Primitive
623  {
624    pf_generic_function_documentation() 
625    {
626      super("generic-function-documentation", PACKAGE_SYS, true);
627    }
628    @Override
629    public LispObject execute(LispObject arg)
630    {
631      return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_DOCUMENTATION];
632    }
633  };
634
635  private static final Primitive SET_GENERIC_FUNCTION_DOCUMENTATION
636    = new pf_set_generic_function_documentation();
637  @DocString(name="set-generic-function-documentation")
638  private static final class pf_set_generic_function_documentation extends Primitive
639  {
640    pf_set_generic_function_documentation()
641    {
642      super("set-generic-function-documentation", PACKAGE_SYS, true);
643    }
644    @Override
645    public LispObject execute(LispObject first, LispObject second)
646    {
647      checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_DOCUMENTATION] 
648        = second;
649      return second;
650    }
651  };
652
653  private static final Primitive _FINALIZE_GENERIC_FUNCTION
654    = new pf__finalize_generic_function();
655  @DocString(name="%finalize-generic-function",
656             args="generic-function")
657  private static final class  pf__finalize_generic_function extends Primitive
658  {
659    pf__finalize_generic_function()
660    {
661      super("%finalize-generic-function", PACKAGE_SYS, true,
662            "generic-function");
663    }
664    @Override
665    public LispObject execute(LispObject arg)
666    {
667      final StandardGenericFunction gf = checkStandardGenericFunction(arg);
668      gf.finalizeInternal();       
669      return T;
670    }
671  };
672
673  private static final Primitive CACHE_EMF
674    = new pf_cache_emf();
675  @DocString(name="cache-emf",
676             args="generic-function args emf")
677  private static final class pf_cache_emf extends Primitive
678  {
679    pf_cache_emf()
680    {
681      super("cache-emf", PACKAGE_SYS, true, "generic-function args emf");
682    }
683    @Override
684    public LispObject execute(LispObject first, LispObject second,
685                              LispObject third)
686    {
687      final StandardGenericFunction gf = checkStandardGenericFunction(first);
688      LispObject args = second;
689      LispObject[] array = new LispObject[gf.numberOfRequiredArgs];
690      for (int i = gf.numberOfRequiredArgs; i-- > 0;)
691        {
692          array[i] = gf.getArgSpecialization(args.car());
693          args = args.cdr();
694        }
695      CacheEntry specializations = new CacheEntry(array);
696      ConcurrentHashMap<CacheEntry,LispObject> ht = gf.cache;
697      if (ht == null)
698        ht = gf.cache = new ConcurrentHashMap<CacheEntry,LispObject>();
699      ht.put(specializations, third);
700      return third;
701    }
702  };
703
704  private static final Primitive GET_CACHED_EMF
705    = new pf_get_cached_emf();
706  @DocString(name="get-cached-emf",
707             args="generic-function args")
708  private static final class pf_get_cached_emf extends Primitive
709  {
710    pf_get_cached_emf() {
711      super("get-cached-emf", PACKAGE_SYS, true, "generic-function args");
712    }
713    @Override
714    public LispObject execute(LispObject first, LispObject second)
715    {
716      final StandardGenericFunction gf = checkStandardGenericFunction(first);
717      LispObject args = second;
718      LispObject[] array = new LispObject[gf.numberOfRequiredArgs];
719      for (int i = gf.numberOfRequiredArgs; i-- > 0;)
720        {
721          array[i] = gf.getArgSpecialization(args.car());
722          args = args.cdr();
723        }
724      CacheEntry specializations = new CacheEntry(array);
725      ConcurrentHashMap<CacheEntry,LispObject> ht = gf.cache;
726      if (ht == null)
727        return NIL;
728      LispObject emf = (LispObject) ht.get(specializations);
729      return emf != null ? emf : NIL;
730    }
731  };
732
733  /**
734   * Returns an object representing generic function
735   * argument <tt>arg</tt> in a <tt>CacheEntry</tt>
736   *
737   * <p>In the simplest case, when this generic function
738   * does not have EQL specialized methods, and therefore
739   * only argument types are relevant for choosing
740   * applicable methods, the value returned is the
741   * class of <tt>arg</tt>
742   *
743   * <p>If the function has EQL specialized methods:
744   *   - if <tt>arg</tt> is EQL to some of the EQL-specializers,
745   *     a special object representing equality to that specializer
746   *     is returned.
747   *   - otherwise class of the <tt>arg</tt> is returned.
748   *
749   * <p>Note that we do not consider argument position, when
750   * calculating arg specialization. In rare cases (when one argument
751   * is eql-specialized to a symbol specifying class of another
752   * argument) this may result in redundant cache entries caching the
753   * same method. But the method cached is anyway correct for the
754   * arguments (because in case of cache miss, correct method is
755   * calculated by other code, which does not rely on
756   * getArgSpecialization; and because EQL is true only for objects of
757   * the same type, which guaranties that if a type-specialized
758   * methods was chached by eql-specialization, all the cache hits
759   * into this records will be from args of the conforming type).
760   *
761   * <p>Consider:
762   * <pre><tt>
763   * (defgeneric f (a b))
764   *
765   * (defmethod f (a (b (eql 'symbol)))
766   *   "T (EQL 'SYMBOL)")
767   *
768   * (defmethod f ((a symbol) (b (eql 'symbol)))
769   *   "SYMBOL (EQL 'SYMBOL)")
770   *
771   * (f 12 'symbol)
772   * => "T (EQL 'SYMBOL)"
773   *
774   * (f 'twelve 'symbol)
775   * => "SYMBOL (EQL 'SYMBOL)"
776   *
777   * (f 'symbol 'symbol)
778   * => "SYMBOL (EQL 'SYMBOL)"
779   *
780   * </tt></pre>
781   *
782   * After the two above calls <tt>cache</tt> will contain three keys:
783   * <pre>
784   * { class FIXNUM, EqlSpecialization('SYMBOL) }
785   * { class SYMBOL, EqlSpecialization('SYMBOL) }
786   * { EqlSpecialization('SYMBOL), EqlSpecialization('SYMBOL) }.
787   * </pre>
788   */     
789  LispObject getArgSpecialization(LispObject arg)
790  {
791    for (EqlSpecialization eqlSpecialization : eqlSpecializations)
792      {
793        if (eqlSpecialization.eqlTo.eql(arg))
794          return eqlSpecialization;
795      }
796    return arg.classOf();
797  }
798
799  private static final Primitive _GET_ARG_SPECIALIZATION
800    = new pf__get_arg_specialization();
801  @DocString(name="%get-arg-specialization",
802             args="generic-function arg")
803  private static final class pf__get_arg_specialization extends Primitive
804  {
805    pf__get_arg_specialization() 
806    {
807      super("%get-arg-specialization", PACKAGE_SYS, true, "generic-function arg");
808    }
809    @Override
810    public LispObject execute(LispObject first, LispObject second)
811    {
812      final StandardGenericFunction gf = checkStandardGenericFunction(first);
813      return gf.getArgSpecialization(second);
814    }
815  };
816
817  private static final Primitive CACHE_SLOT_LOCATION
818    = new pf_cache_slot_location(); 
819  @DocString(name="cache-slot-location",
820           args="generic-function layout location")
821  private static final class pf_cache_slot_location extends Primitive
822  {
823    pf_cache_slot_location()
824    {
825      super("cache-slot-location", PACKAGE_SYS, true, "generic-function layout location");
826    }
827    @Override
828    public LispObject execute(LispObject first, LispObject second,
829                                LispObject third)
830    {
831      final StandardGenericFunction gf = checkStandardGenericFunction(first);
832      LispObject layout = second;
833      LispObject location = third;
834      ConcurrentHashMap<LispObject,LispObject> ht = gf.slotCache;
835      if (ht == null)
836        ht = gf.slotCache = new ConcurrentHashMap<LispObject,LispObject>();
837      ht.put(layout, location);
838      return third;
839    }
840  };
841
842  private static final Primitive GET_CACHED_SLOT_LOCATION
843    = new pf_get_cached_slot_location();
844  @DocString(name="get-cached-slot-location")
845  private static final class pf_get_cached_slot_location extends Primitive
846  {
847    pf_get_cached_slot_location()
848    {
849      super("get-cached-slot-location", PACKAGE_SYS, true, "generic-function layout");
850    }
851    @Override
852    public LispObject execute(LispObject first, LispObject second)
853    {
854      final StandardGenericFunction gf = checkStandardGenericFunction(first);
855      LispObject layout = second;
856      ConcurrentHashMap<LispObject,LispObject> ht = gf.slotCache;
857      if (ht == null)
858        return NIL;
859      LispObject location = (LispObject) ht.get(layout);
860      return location != null ? location : NIL;
861    }
862  };
863
864  private static final StandardGenericFunction GENERIC_FUNCTION_NAME =
865    new StandardGenericFunction("generic-function-name",
866                                PACKAGE_MOP,
867                                true,
868                                _GENERIC_FUNCTION_NAME,
869                                list(Symbol.GENERIC_FUNCTION),
870                                list(StandardClass.STANDARD_GENERIC_FUNCTION));
871
872  private static class CacheEntry
873  {
874    final LispObject[] array;
875
876    CacheEntry(LispObject[] array)
877    {
878      this.array = array;
879    }
880
881    @Override
882    public int hashCode()
883    {
884      int result = 0;
885      for (int i = array.length; i-- > 0;)
886        result ^= array[i].hashCode();
887      return result;
888    }
889
890    @Override
891    public boolean equals(Object object)
892    {
893      if (!(object instanceof CacheEntry))
894        return false;
895      final CacheEntry otherEntry = (CacheEntry) object;
896      if (otherEntry.array.length != array.length)
897        return false;
898      final LispObject[] otherArray = otherEntry.array;
899      for (int i = array.length; i-- > 0;)
900        if (array[i] != otherArray[i])
901          return false;
902      return true;
903    }
904  }
905
906  EqlSpecialization eqlSpecializations[] = new EqlSpecialization[0];
907
908  private static final Primitive _INIT_EQL_SPECIALIZATIONS 
909    = new pf__init_eql_specializations();
910  @DocString(name="%init-eql-specializations",
911             args="generic-function eql-specilizer-objects-list")
912  private static final class pf__init_eql_specializations extends Primitive
913  {
914    pf__init_eql_specializations()
915    {
916      super("%init-eql-specializations", PACKAGE_SYS, true, 
917            "generic-function eql-specilizer-objects-list");
918    }
919    @Override
920    public LispObject execute(LispObject first, LispObject second)
921    {
922      final StandardGenericFunction gf = checkStandardGenericFunction(first);
923      LispObject eqlSpecializerObjects = second;
924      gf.eqlSpecializations = new EqlSpecialization[eqlSpecializerObjects.length()];
925      for (int i = 0; i < gf.eqlSpecializations.length; i++) {
926        gf.eqlSpecializations[i] = new EqlSpecialization(eqlSpecializerObjects.car());
927        eqlSpecializerObjects = eqlSpecializerObjects.cdr();
928      }
929      return NIL;
930    }
931  };
932
933  private static class EqlSpecialization extends LispObject
934  {
935    public LispObject eqlTo;
936
937    public EqlSpecialization(LispObject eqlTo)
938    {
939        this.eqlTo = eqlTo;
940    }
941  }
942 
943  public static final StandardGenericFunction checkStandardGenericFunction(LispObject obj)
944  {
945    if (obj instanceof StandardGenericFunction)
946      return (StandardGenericFunction) obj;
947    return (StandardGenericFunction) // Not reached.
948      type_error(obj, Symbol.STANDARD_GENERIC_FUNCTION);
949  }
950}
Note: See TracBrowser for help on using the repository browser.