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

Last change on this file was 12576, checked in by ehuelsmann, 15 years ago

Re #38: Merge the METACLASS branch to trunk.

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