source: trunk/abcl/src/org/armedbear/lisp/LispClass.java @ 12381

Last change on this file since 12381 was 12356, checked in by ehuelsmann, 15 years ago

Make LispClass?.addClass return the added class, for convenience.

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