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

Last change on this file was 11754, checked in by vvoutilainen, 16 years ago

Convert using ClassCastException? to checking instanceof.
Performance tests show this approach to be faster.
Patch by Douglas R. Miles. I modified the patch to
remove tabs, so indentation may be slightly off in places.
That's something that we need to handle separately, abcl
doesn't have a clear indentation policy.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.2 KB
Line 
1/*
2 * LispClass.java
3 *
4 * Copyright (C) 2003-2005 Peter Graves
5 * $Id: LispClass.java 11754 2009-04-12 10:53:39Z vvoutilainen $
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
36public abstract class LispClass extends StandardObject
37{
38  private static final EqHashTable map = new EqHashTable(256, NIL, NIL);
39
40  public static void addClass(Symbol symbol, LispClass c)
41  {
42    synchronized (map)
43      {
44        map.put(symbol, c);
45      }
46  }
47
48  public static void removeClass(Symbol symbol)
49  {
50    synchronized (map)
51      {
52        map.remove(symbol);
53      }
54  }
55
56  public static LispClass findClass(Symbol symbol)
57  {
58    synchronized (map)
59      {
60        return (LispClass) map.get(symbol);
61      }
62  }
63
64  public static LispObject findClass(LispObject name, boolean errorp)
65    throws ConditionThrowable
66  {
67    final Symbol symbol = checkSymbol(name);
68    final LispClass c;
69    synchronized (map)
70      {
71        c = (LispClass) map.get(symbol);
72      }
73    if (c != null)
74      return c;
75    if (errorp)
76      {
77        FastStringBuffer sb =
78          new FastStringBuffer("There is no class named ");
79        sb.append(name.writeToString());
80        sb.append('.');
81        return error(new LispError(sb.toString()));
82      }
83    return NIL;
84  }
85
86  private final int sxhash;
87
88  protected Symbol symbol;
89  private LispObject propertyList;
90  private Layout classLayout;
91  private LispObject directSuperclasses = NIL;
92  private LispObject directSubclasses = NIL;
93  public LispObject classPrecedenceList = NIL; // FIXME! Should be private!
94  public LispObject directMethods = NIL; // FIXME! Should be private!
95  public LispObject documentation = NIL; // FIXME! Should be private!
96  private boolean finalized;
97
98  protected LispClass()
99  {
100    sxhash = hashCode() & 0x7fffffff;
101  }
102
103  protected LispClass(Symbol symbol)
104  {
105    sxhash = hashCode() & 0x7fffffff;
106    this.symbol = symbol;
107    this.directSuperclasses = NIL;
108  }
109
110  protected LispClass(Symbol symbol, LispObject directSuperclasses)
111  {
112    sxhash = hashCode() & 0x7fffffff;
113    this.symbol = symbol;
114    this.directSuperclasses = directSuperclasses;
115  }
116
117  @Override
118  public LispObject getParts() throws ConditionThrowable
119  {
120    LispObject result = NIL;
121    result = result.push(new Cons("NAME", symbol != null ? symbol : NIL));
122    result = result.push(new Cons("LAYOUT", classLayout != null ? classLayout : NIL));
123    result = result.push(new Cons("DIRECT-SUPERCLASSES", directSuperclasses));
124    result = result.push(new Cons("DIRECT-SUBCLASSES", directSubclasses));
125    result = result.push(new Cons("CLASS-PRECEDENCE-LIST", classPrecedenceList));
126    result = result.push(new Cons("DIRECT-METHODS", directMethods));
127    result = result.push(new Cons("DOCUMENTATION", documentation));
128    return result.nreverse();
129  }
130
131  @Override
132  public final int sxhash()
133  {
134    return sxhash;
135  }
136
137  public final Symbol getSymbol()
138  {
139    return symbol;
140  }
141
142  @Override
143  public final LispObject getPropertyList()
144  {
145    if (propertyList == null)
146      propertyList = NIL;
147    return propertyList;
148  }
149
150  @Override
151  public final void setPropertyList(LispObject obj)
152  {
153    if (obj == null)
154      throw new NullPointerException();
155    propertyList = obj;
156  }
157
158  public final Layout getClassLayout()
159  {
160    return classLayout;
161  }
162
163  public final void setClassLayout(Layout layout)
164  {
165    classLayout = layout;
166  }
167
168  public final int getLayoutLength()
169  {
170    if (layout == null)
171      return 0;
172    return layout.getLength();
173  }
174
175  public final LispObject getDirectSuperclasses()
176  {
177    return directSuperclasses;
178  }
179
180  public final void setDirectSuperclasses(LispObject directSuperclasses)
181  {
182    this.directSuperclasses = directSuperclasses;
183  }
184
185  public final boolean isFinalized()
186  {
187    return finalized;
188  }
189
190  public final void setFinalized(boolean b)
191  {
192    finalized = b;
193  }
194
195  // When there's only one direct superclass...
196  public final void setDirectSuperclass(LispObject superclass)
197  {
198    directSuperclasses = new Cons(superclass);
199  }
200
201  public final LispObject getDirectSubclasses()
202  {
203    return directSubclasses;
204  }
205
206  public final void setDirectSubclasses(LispObject directSubclasses)
207  {
208    this.directSubclasses = directSubclasses;
209  }
210
211  public final LispObject getCPL()
212  {
213    return classPrecedenceList;
214  }
215
216  public final void setCPL(LispObject obj1)
217  {
218    if (obj1 instanceof Cons)
219      classPrecedenceList = obj1;
220    else
221      {
222        Debug.assertTrue(obj1 == this);
223        classPrecedenceList = new Cons(obj1);
224      }
225  }
226
227  public final void setCPL(LispObject obj1, LispObject obj2)
228  {
229    Debug.assertTrue(obj1 == this);
230    classPrecedenceList = list(obj1, obj2);
231  }
232
233  public final void setCPL(LispObject obj1, LispObject obj2, LispObject obj3)
234  {
235    Debug.assertTrue(obj1 == this);
236    classPrecedenceList = list(obj1, obj2, obj3);
237  }
238
239  public final void setCPL(LispObject obj1, LispObject obj2, LispObject obj3,
240                           LispObject obj4)
241  {
242    Debug.assertTrue(obj1 == this);
243    classPrecedenceList = list(obj1, obj2, obj3, obj4);
244  }
245
246  public final void setCPL(LispObject obj1, LispObject obj2, LispObject obj3,
247                           LispObject obj4, LispObject obj5)
248  {
249    Debug.assertTrue(obj1 == this);
250    classPrecedenceList = list(obj1, obj2, obj3, obj4, obj5);
251  }
252
253  public final void setCPL(LispObject obj1, LispObject obj2, LispObject obj3,
254                           LispObject obj4, LispObject obj5, LispObject obj6)
255  {
256    Debug.assertTrue(obj1 == this);
257    classPrecedenceList = list(obj1, obj2, obj3, obj4, obj5, obj6);
258  }
259
260  public final void setCPL(LispObject obj1, LispObject obj2, LispObject obj3,
261                           LispObject obj4, LispObject obj5, LispObject obj6,
262                           LispObject obj7)
263  {
264    Debug.assertTrue(obj1 == this);
265    classPrecedenceList = list(obj1, obj2, obj3, obj4, obj5, obj6, obj7);
266  }
267
268  public final void setCPL(LispObject obj1, LispObject obj2, LispObject obj3,
269                           LispObject obj4, LispObject obj5, LispObject obj6,
270                           LispObject obj7, LispObject obj8)
271  {
272    Debug.assertTrue(obj1 == this);
273    classPrecedenceList =
274      list(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8);
275  }
276
277  public final void setCPL(LispObject obj1, LispObject obj2, LispObject obj3,
278                           LispObject obj4, LispObject obj5, LispObject obj6,
279                           LispObject obj7, LispObject obj8, LispObject obj9)
280  {
281    Debug.assertTrue(obj1 == this);
282    classPrecedenceList =
283      list(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9);
284  }
285
286  public String getName()
287  {
288    return symbol.getName();
289  }
290
291  @Override
292  public LispObject typeOf()
293  {
294    return Symbol.CLASS;
295  }
296
297  @Override
298  public LispObject classOf()
299  {
300    return StandardClass.CLASS;
301  }
302
303  @Override
304  public LispObject typep(LispObject type) throws ConditionThrowable
305  {
306    if (type == Symbol.CLASS)
307      return T;
308    if (type == StandardClass.CLASS)
309      return T;
310    return super.typep(type);
311  }
312
313  public boolean subclassp(LispObject obj) throws ConditionThrowable
314  {
315    LispObject cpl = classPrecedenceList;
316    while (cpl != NIL)
317      {
318        if (cpl.car() == obj)
319          return true;
320        cpl = ((Cons)cpl).cdr;
321      }
322    return false;
323  }
324
325  // ### find-class symbol &optional errorp environment => class
326  private static final Primitive FIND_CLASS =
327    new Primitive(Symbol.FIND_CLASS, "symbol &optional errorp environment")
328    {
329      @Override
330      public LispObject execute(LispObject arg) throws ConditionThrowable
331      {
332        return findClass(arg, true);
333      }
334      @Override
335      public LispObject execute(LispObject first, LispObject second)
336        throws ConditionThrowable
337      {
338        return findClass(first, second != NIL);
339      }
340      @Override
341      public LispObject execute(LispObject first, LispObject second,
342                                LispObject third)
343        throws ConditionThrowable
344      {
345        // FIXME Use environment!
346        return findClass(first, second != NIL);
347      }
348    };
349
350  // ### %set-find-class
351  private static final Primitive _SET_FIND_CLASS =
352    new Primitive("%set-find-class", PACKAGE_SYS, true)
353    {
354      @Override
355      public LispObject execute(LispObject first, LispObject second)
356        throws ConditionThrowable
357      {
358        final Symbol name = checkSymbol(first);
359        if (second == NIL)
360          {
361            removeClass(name);
362            return second;
363          }
364        final LispClass c = checkClass(second);
365        addClass(name, c);
366        return second;
367      }
368    };
369
370  // ### subclassp
371  private static final Primitive SUBCLASSP =
372    new Primitive(Symbol.SUBCLASSP, "class")
373    {
374      @Override
375      public LispObject execute(LispObject first, LispObject second)
376        throws ConditionThrowable
377      {
378        final LispClass c = checkClass(first);
379        return c.subclassp(second) ? T : NIL;
380      }
381    };
382}
Note: See TracBrowser for help on using the repository browser.