source: branches/1.1.x/src/org/armedbear/lisp/SlotClass.java

Last change on this file was 14134, checked in by rschlatte, 12 years ago

Handle instances of subclasses of standard-slot-definition in accessors

  • Subclasses of standard-(direct|effective)-slot-definition are of Java class StandardObject? and might have different class layout.
  • Keep the fast, fixed-indexing path for objects of Java class SlotDefinition?, handle other objects via slot-name-based indexing.
  • Thanks to Stas Boukarev and Pascal Costanza for error reports and diagnosis.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 11.5 KB
Line 
1/*
2 * SlotClass.java
3 *
4 * Copyright (C) 2003-2005 Peter Graves
5 * $Id: SlotClass.java 14134 2012-08-25 21:14:49Z rschlatte $
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 class SlotClass extends LispClass
39{
40    private LispObject directSlotDefinitions = NIL;
41    private LispObject slotDefinitions = NIL;
42    private LispObject directDefaultInitargs = NIL;
43    private LispObject defaultInitargs = NIL;
44
45    public SlotClass(Layout layout)
46    {
47      super(layout);
48    }
49
50    public SlotClass(Symbol symbol, LispObject directSuperclasses)
51
52
53    {
54        this(null, symbol, directSuperclasses);
55    }
56
57    public SlotClass(Layout layout,
58                     Symbol symbol, LispObject directSuperclasses)
59    {
60        super(layout, symbol, directSuperclasses);
61    }
62
63    @Override
64    public LispObject getParts()
65    {
66        LispObject result = super.getParts().nreverse();
67        result = result.push(new Cons("DIRECT-SLOTS",
68                                      getDirectSlotDefinitions()));
69        result = result.push(new Cons("SLOTS", getSlotDefinitions()));
70        result = result.push(new Cons("DIRECT-DEFAULT-INITARGS",
71                                      getDirectDefaultInitargs()));
72        result = result.push(new Cons("DEFAULT-INITARGS",
73                                      getDefaultInitargs()));
74        return result.nreverse();
75    }
76
77    @Override
78    public LispObject typep(LispObject type)
79    {
80        return super.typep(type);
81    }
82
83    public LispObject getDirectSlotDefinitions()
84    {
85        return directSlotDefinitions;
86    }
87
88    public void setDirectSlotDefinitions(LispObject directSlotDefinitions)
89    {
90        this.directSlotDefinitions = directSlotDefinitions;
91    }
92
93    public LispObject getSlotDefinitions()
94    {
95        return slotDefinitions;
96    }
97
98    public void setSlotDefinitions(LispObject slotDefinitions)
99    {
100        this.slotDefinitions = slotDefinitions;
101    }
102
103    public LispObject getDirectDefaultInitargs()
104    {
105        return directDefaultInitargs;
106    }
107
108    public void setDirectDefaultInitargs(LispObject directDefaultInitargs)
109    {
110        this.directDefaultInitargs = directDefaultInitargs;
111    }
112
113    public LispObject getDefaultInitargs()
114    {
115        return defaultInitargs;
116    }
117
118    public void setDefaultInitargs(LispObject defaultInitargs)
119    {
120        this.defaultInitargs = defaultInitargs;
121    }
122
123    LispObject computeDefaultInitargs()
124    {
125      // KLUDGE (rudi 2012-06-02): duplicate initargs are not removed
126      // here, but this does not hurt us since no Lisp class we define
127      // Java-side has non-nil direct default initargs.
128        LispObject result = NIL;
129        LispObject cpl = getCPL();
130        while (cpl != NIL) {
131            LispClass c = (LispClass) cpl.car();
132            if (c instanceof StandardClass) {
133                LispObject obj = ((StandardClass)c).getDirectDefaultInitargs();
134                if (obj != NIL)
135                    result = Symbol.APPEND.execute(result, obj);
136            }
137            cpl = cpl.cdr();
138        }
139        return result;
140    }
141
142    public void finalizeClass()
143    {
144        if (isFinalized())
145            return;
146
147        LispObject defs = getSlotDefinitions();
148        Debug.assertTrue(defs == NIL);
149        LispObject cpl = getCPL();
150        Debug.assertTrue(cpl != null);
151        Debug.assertTrue(cpl.listp());
152        cpl = cpl.reverse();
153        while (cpl != NIL) {
154            LispObject car = cpl.car();
155            if (car instanceof StandardClass) {
156                StandardClass cls = (StandardClass) car;
157                LispObject directDefs = cls.getDirectSlotDefinitions();
158                Debug.assertTrue(directDefs != null);
159                Debug.assertTrue(directDefs.listp());
160                while (directDefs != NIL) {
161                    defs = defs.push(directDefs.car());
162                    directDefs = directDefs.cdr();
163                }
164            }
165            cpl = cpl.cdr();
166        }
167        setSlotDefinitions(defs.nreverse());
168        LispObject[] instanceSlotNames = new LispObject[defs.length()];
169        int i = 0;
170        LispObject tail = getSlotDefinitions();
171        while (tail != NIL) {
172            SlotDefinition slotDefinition = (SlotDefinition) tail.car();
173            SlotDefinition.SET_SLOT_DEFINITION_LOCATION
174              .execute(slotDefinition, Fixnum.getInstance(i));
175            instanceSlotNames[i++] = SlotDefinition._SLOT_DEFINITION_NAME
176              .execute(slotDefinition);
177            tail = tail.cdr();
178        }
179        setClassLayout(new Layout(this, instanceSlotNames, NIL));
180        setDefaultInitargs(computeDefaultInitargs());
181        setFinalized(true);
182    }
183
184    @DocString(name="%class-direct-slots")
185    private static final Primitive CLASS_DIRECT_SLOTS
186        = new pf__class_direct_slots();
187    private static final class pf__class_direct_slots extends Primitive
188    {
189        pf__class_direct_slots() 
190        {
191            super("%class-direct-slots", PACKAGE_SYS, true);
192        }
193        @Override
194        public LispObject execute(LispObject arg)
195
196        {
197            if (arg instanceof SlotClass)
198                return ((SlotClass)arg).getDirectSlotDefinitions();
199            if (arg instanceof BuiltInClass)
200                return NIL;
201            return type_error(arg, Symbol.STANDARD_CLASS);
202        }
203    };
204
205    @DocString(name="%set-class-direct-slots")
206    private static final Primitive _SET_CLASS_DIRECT_SLOT
207        = new pf__set_class_direct_slots();
208    private static final class pf__set_class_direct_slots extends Primitive
209    {
210        pf__set_class_direct_slots() 
211        {
212            super("%set-class-direct-slots", PACKAGE_SYS, true);
213        }
214
215        @Override
216        public LispObject execute(LispObject first, LispObject second)
217        {
218            if (second instanceof SlotClass) {
219                  ((SlotClass)second).setDirectSlotDefinitions(first);
220                return first;
221            } else {
222                return type_error(second, Symbol.STANDARD_CLASS);
223            }
224        }
225    };
226
227    @DocString(name="%class-slots",
228               args="class")
229    private static final Primitive _CLASS_SLOTS
230        = new pf__class_slots();
231    private static final class pf__class_slots extends Primitive
232    {
233        pf__class_slots() 
234        {
235            super(Symbol._CLASS_SLOTS, "class");
236        }
237
238        @Override
239        public LispObject execute(LispObject arg)
240        {
241            if (arg instanceof SlotClass)
242                return ((SlotClass)arg).getSlotDefinitions();
243            if (arg instanceof BuiltInClass)
244                return NIL;
245            return type_error(arg, Symbol.STANDARD_CLASS);
246        }
247    };
248
249    @DocString(name="%set-class-slots",
250               args="class slot-definitions")
251    private static final Primitive _SET_CLASS_SLOTS
252        = new pf__set_class_slots();
253    private static final class pf__set_class_slots extends Primitive
254    {
255        pf__set_class_slots()
256        {
257            super(Symbol._SET_CLASS_SLOTS, "class slot-definitions");
258        }
259        @Override
260        public LispObject execute(LispObject first, LispObject second)
261        {
262            if (second instanceof SlotClass) {
263              ((SlotClass)second).setSlotDefinitions(first);
264              return first;
265            } else {
266              return type_error(second, Symbol.STANDARD_CLASS);
267            }
268        }
269    };
270
271    @DocString(name="%class-direct-default-initargs")
272    private static final Primitive CLASS_DIRECT_DEFAULT_INITARGS
273        = new pf__class_direct_default_initargs();
274    private static final class pf__class_direct_default_initargs extends Primitive
275    {
276        pf__class_direct_default_initargs() 
277        {
278            super("%class-direct-default-initargs", PACKAGE_SYS, true);
279        }
280        @Override
281        public LispObject execute(LispObject arg)
282        {
283            if (arg instanceof SlotClass)
284                return ((SlotClass)arg).getDirectDefaultInitargs();
285            if (arg instanceof BuiltInClass)
286                return NIL;
287            return type_error(arg, Symbol.STANDARD_CLASS);
288        }
289    };
290
291    @DocString(name="%set-class-direct-default-initargs")
292    private static final Primitive _SET_CLASS_DIRECT_DEFAULT_INITARGS
293        = new pf__set_class_direct_default_initargs();
294    private static final class pf__set_class_direct_default_initargs extends Primitive
295    {
296        pf__set_class_direct_default_initargs()
297        {
298            super("%set-class-direct-default-initargs", PACKAGE_SYS, true);
299        }
300        @Override
301        public LispObject execute(LispObject first, LispObject second)
302        {
303            if (second instanceof SlotClass) {
304                ((SlotClass)second).setDirectDefaultInitargs(first);
305                return first;
306            }
307            return type_error(second, Symbol.STANDARD_CLASS);
308        }
309    };
310
311    @DocString(name="%class-default-initargs")
312    private static final Primitive CLASS_DEFAULT_INITARGS
313        = new pf__class_default_initargs();
314    private static final class pf__class_default_initargs extends Primitive
315    {
316        pf__class_default_initargs() 
317        {
318            super("%class-default-initargs", PACKAGE_SYS, true);
319        }
320        @Override
321        public LispObject execute(LispObject arg)
322        {
323            if (arg instanceof SlotClass)
324                return ((SlotClass)arg).getDefaultInitargs();
325            if (arg instanceof BuiltInClass)
326                return NIL;
327            return type_error(arg, Symbol.STANDARD_CLASS);
328        }
329    };
330
331    @DocString(name="%set-class-default-initargs")
332    private static final Primitive _SET_CLASS_DEFAULT_INITARGS
333        = new pf__set_class_default_initargs();
334
335    private static final class pf__set_class_default_initargs extends Primitive
336    {
337        pf__set_class_default_initargs()
338        {
339            super("%set-class-default-initargs", PACKAGE_SYS, true);
340        }
341        @Override
342        public LispObject execute(LispObject first, LispObject second)
343        {
344            if (second instanceof SlotClass) {
345                ((SlotClass)second).setDefaultInitargs(first);
346                return first;
347            }
348            return type_error(second, Symbol.STANDARD_CLASS);
349        }
350    };
351}
Note: See TracBrowser for help on using the repository browser.