[946] | 1 | /* |
---|
| 2 | * LispClass.java |
---|
| 3 | * |
---|
[9189] | 4 | * Copyright (C) 2003-2005 Peter Graves |
---|
[11297] | 5 | * $Id: LispClass.java 12356 2010-01-10 14:57:39Z ehuelsmann $ |
---|
[946] | 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. |
---|
[11391] | 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. |
---|
[946] | 32 | */ |
---|
| 33 | |
---|
| 34 | package org.armedbear.lisp; |
---|
| 35 | |
---|
[12288] | 36 | import static org.armedbear.lisp.Lisp.*; |
---|
| 37 | |
---|
[10378] | 38 | public abstract class LispClass extends StandardObject |
---|
[946] | 39 | { |
---|
[10843] | 40 | private static final EqHashTable map = new EqHashTable(256, NIL, NIL); |
---|
[946] | 41 | |
---|
[12356] | 42 | public static LispClass addClass(Symbol symbol, LispClass c) |
---|
[10843] | 43 | { |
---|
| 44 | synchronized (map) |
---|
| 45 | { |
---|
| 46 | map.put(symbol, c); |
---|
| 47 | } |
---|
[12356] | 48 | return c; |
---|
[10843] | 49 | } |
---|
[3966] | 50 | |
---|
[10847] | 51 | public static void removeClass(Symbol symbol) |
---|
| 52 | { |
---|
| 53 | synchronized (map) |
---|
| 54 | { |
---|
| 55 | map.remove(symbol); |
---|
| 56 | } |
---|
| 57 | } |
---|
| 58 | |
---|
[10843] | 59 | public static LispClass findClass(Symbol symbol) |
---|
| 60 | { |
---|
| 61 | synchronized (map) |
---|
| 62 | { |
---|
| 63 | return (LispClass) map.get(symbol); |
---|
| 64 | } |
---|
| 65 | } |
---|
[9189] | 66 | |
---|
[10847] | 67 | public static LispObject findClass(LispObject name, boolean errorp) |
---|
[12254] | 68 | |
---|
[10843] | 69 | { |
---|
[11754] | 70 | final Symbol symbol = checkSymbol(name); |
---|
[10847] | 71 | final LispClass c; |
---|
[10843] | 72 | synchronized (map) |
---|
| 73 | { |
---|
[10847] | 74 | c = (LispClass) map.get(symbol); |
---|
[10843] | 75 | } |
---|
[10847] | 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('.'); |
---|
[11158] | 84 | return error(new LispError(sb.toString())); |
---|
[10847] | 85 | } |
---|
| 86 | return NIL; |
---|
[10843] | 87 | } |
---|
[3966] | 88 | |
---|
[10843] | 89 | private final int sxhash; |
---|
[10825] | 90 | |
---|
[10843] | 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; |
---|
[946] | 100 | |
---|
[10843] | 101 | protected LispClass() |
---|
| 102 | { |
---|
| 103 | sxhash = hashCode() & 0x7fffffff; |
---|
| 104 | } |
---|
[4280] | 105 | |
---|
[10843] | 106 | protected LispClass(Symbol symbol) |
---|
| 107 | { |
---|
| 108 | sxhash = hashCode() & 0x7fffffff; |
---|
| 109 | this.symbol = symbol; |
---|
| 110 | this.directSuperclasses = NIL; |
---|
| 111 | } |
---|
[946] | 112 | |
---|
[10843] | 113 | protected LispClass(Symbol symbol, LispObject directSuperclasses) |
---|
| 114 | { |
---|
| 115 | sxhash = hashCode() & 0x7fffffff; |
---|
| 116 | this.symbol = symbol; |
---|
| 117 | this.directSuperclasses = directSuperclasses; |
---|
| 118 | } |
---|
[3966] | 119 | |
---|
[11488] | 120 | @Override |
---|
[12254] | 121 | public LispObject getParts() |
---|
[10843] | 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 | } |
---|
[6876] | 133 | |
---|
[11488] | 134 | @Override |
---|
[10843] | 135 | public final int sxhash() |
---|
| 136 | { |
---|
| 137 | return sxhash; |
---|
| 138 | } |
---|
[10825] | 139 | |
---|
[10843] | 140 | public final Symbol getSymbol() |
---|
| 141 | { |
---|
| 142 | return symbol; |
---|
| 143 | } |
---|
[2942] | 144 | |
---|
[11488] | 145 | @Override |
---|
[10843] | 146 | public final LispObject getPropertyList() |
---|
| 147 | { |
---|
| 148 | if (propertyList == null) |
---|
| 149 | propertyList = NIL; |
---|
| 150 | return propertyList; |
---|
| 151 | } |
---|
[9189] | 152 | |
---|
[11488] | 153 | @Override |
---|
[10843] | 154 | public final void setPropertyList(LispObject obj) |
---|
| 155 | { |
---|
| 156 | if (obj == null) |
---|
| 157 | throw new NullPointerException(); |
---|
| 158 | propertyList = obj; |
---|
| 159 | } |
---|
[9189] | 160 | |
---|
[10843] | 161 | public final Layout getClassLayout() |
---|
| 162 | { |
---|
| 163 | return classLayout; |
---|
| 164 | } |
---|
[5066] | 165 | |
---|
[10843] | 166 | public final void setClassLayout(Layout layout) |
---|
| 167 | { |
---|
| 168 | classLayout = layout; |
---|
| 169 | } |
---|
[5066] | 170 | |
---|
[10843] | 171 | public final int getLayoutLength() |
---|
| 172 | { |
---|
| 173 | if (layout == null) |
---|
| 174 | return 0; |
---|
| 175 | return layout.getLength(); |
---|
| 176 | } |
---|
[9462] | 177 | |
---|
[10843] | 178 | public final LispObject getDirectSuperclasses() |
---|
| 179 | { |
---|
| 180 | return directSuperclasses; |
---|
| 181 | } |
---|
[3966] | 182 | |
---|
[10843] | 183 | public final void setDirectSuperclasses(LispObject directSuperclasses) |
---|
| 184 | { |
---|
| 185 | this.directSuperclasses = directSuperclasses; |
---|
| 186 | } |
---|
[3966] | 187 | |
---|
[10843] | 188 | public final boolean isFinalized() |
---|
| 189 | { |
---|
| 190 | return finalized; |
---|
| 191 | } |
---|
[8141] | 192 | |
---|
[10843] | 193 | public final void setFinalized(boolean b) |
---|
| 194 | { |
---|
| 195 | finalized = b; |
---|
| 196 | } |
---|
[8141] | 197 | |
---|
[10843] | 198 | // When there's only one direct superclass... |
---|
| 199 | public final void setDirectSuperclass(LispObject superclass) |
---|
| 200 | { |
---|
| 201 | directSuperclasses = new Cons(superclass); |
---|
| 202 | } |
---|
[3966] | 203 | |
---|
[10843] | 204 | public final LispObject getDirectSubclasses() |
---|
| 205 | { |
---|
| 206 | return directSubclasses; |
---|
| 207 | } |
---|
[4288] | 208 | |
---|
[10843] | 209 | public final void setDirectSubclasses(LispObject directSubclasses) |
---|
| 210 | { |
---|
| 211 | this.directSubclasses = directSubclasses; |
---|
| 212 | } |
---|
[4288] | 213 | |
---|
[10843] | 214 | public final LispObject getCPL() |
---|
| 215 | { |
---|
| 216 | return classPrecedenceList; |
---|
| 217 | } |
---|
[3976] | 218 | |
---|
[10843] | 219 | public final void setCPL(LispObject obj1) |
---|
| 220 | { |
---|
| 221 | if (obj1 instanceof Cons) |
---|
| 222 | classPrecedenceList = obj1; |
---|
| 223 | else |
---|
| 224 | { |
---|
[3976] | 225 | Debug.assertTrue(obj1 == this); |
---|
[10843] | 226 | classPrecedenceList = new Cons(obj1); |
---|
| 227 | } |
---|
| 228 | } |
---|
[3976] | 229 | |
---|
[10843] | 230 | public final void setCPL(LispObject obj1, LispObject obj2) |
---|
| 231 | { |
---|
| 232 | Debug.assertTrue(obj1 == this); |
---|
[11711] | 233 | classPrecedenceList = list(obj1, obj2); |
---|
[10843] | 234 | } |
---|
[3976] | 235 | |
---|
[10843] | 236 | public final void setCPL(LispObject obj1, LispObject obj2, LispObject obj3) |
---|
| 237 | { |
---|
| 238 | Debug.assertTrue(obj1 == this); |
---|
[11711] | 239 | classPrecedenceList = list(obj1, obj2, obj3); |
---|
[10843] | 240 | } |
---|
[3976] | 241 | |
---|
[10843] | 242 | public final void setCPL(LispObject obj1, LispObject obj2, LispObject obj3, |
---|
| 243 | LispObject obj4) |
---|
| 244 | { |
---|
| 245 | Debug.assertTrue(obj1 == this); |
---|
[11711] | 246 | classPrecedenceList = list(obj1, obj2, obj3, obj4); |
---|
[10843] | 247 | } |
---|
[3976] | 248 | |
---|
[10843] | 249 | public final void setCPL(LispObject obj1, LispObject obj2, LispObject obj3, |
---|
| 250 | LispObject obj4, LispObject obj5) |
---|
| 251 | { |
---|
| 252 | Debug.assertTrue(obj1 == this); |
---|
[11711] | 253 | classPrecedenceList = list(obj1, obj2, obj3, obj4, obj5); |
---|
[10843] | 254 | } |
---|
[3976] | 255 | |
---|
[10843] | 256 | public final void setCPL(LispObject obj1, LispObject obj2, LispObject obj3, |
---|
| 257 | LispObject obj4, LispObject obj5, LispObject obj6) |
---|
| 258 | { |
---|
| 259 | Debug.assertTrue(obj1 == this); |
---|
[11711] | 260 | classPrecedenceList = list(obj1, obj2, obj3, obj4, obj5, obj6); |
---|
[10843] | 261 | } |
---|
[3976] | 262 | |
---|
[10843] | 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); |
---|
[11711] | 268 | classPrecedenceList = list(obj1, obj2, obj3, obj4, obj5, obj6, obj7); |
---|
[10843] | 269 | } |
---|
[5075] | 270 | |
---|
[10843] | 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 = |
---|
[11711] | 277 | list(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8); |
---|
[10843] | 278 | } |
---|
[8019] | 279 | |
---|
[10843] | 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 = |
---|
[11711] | 286 | list(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9); |
---|
[10843] | 287 | } |
---|
[946] | 288 | |
---|
[10843] | 289 | public String getName() |
---|
| 290 | { |
---|
| 291 | return symbol.getName(); |
---|
| 292 | } |
---|
[3742] | 293 | |
---|
[11488] | 294 | @Override |
---|
[10843] | 295 | public LispObject typeOf() |
---|
| 296 | { |
---|
| 297 | return Symbol.CLASS; |
---|
| 298 | } |
---|
[946] | 299 | |
---|
[11488] | 300 | @Override |
---|
[10843] | 301 | public LispObject classOf() |
---|
| 302 | { |
---|
| 303 | return StandardClass.CLASS; |
---|
| 304 | } |
---|
[10423] | 305 | |
---|
[11488] | 306 | @Override |
---|
[12254] | 307 | public LispObject typep(LispObject type) |
---|
[10843] | 308 | { |
---|
| 309 | if (type == Symbol.CLASS) |
---|
| 310 | return T; |
---|
| 311 | if (type == StandardClass.CLASS) |
---|
| 312 | return T; |
---|
| 313 | return super.typep(type); |
---|
| 314 | } |
---|
[10427] | 315 | |
---|
[12254] | 316 | public boolean subclassp(LispObject obj) |
---|
[10843] | 317 | { |
---|
| 318 | LispObject cpl = classPrecedenceList; |
---|
| 319 | while (cpl != NIL) |
---|
| 320 | { |
---|
| 321 | if (cpl.car() == obj) |
---|
| 322 | return true; |
---|
[10845] | 323 | cpl = ((Cons)cpl).cdr; |
---|
[10843] | 324 | } |
---|
| 325 | return false; |
---|
| 326 | } |
---|
| 327 | |
---|
[10844] | 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 | { |
---|
[11488] | 332 | @Override |
---|
[12254] | 333 | public LispObject execute(LispObject arg) |
---|
[10844] | 334 | { |
---|
[10847] | 335 | return findClass(arg, true); |
---|
[10844] | 336 | } |
---|
[11488] | 337 | @Override |
---|
[10844] | 338 | public LispObject execute(LispObject first, LispObject second) |
---|
[12254] | 339 | |
---|
[10844] | 340 | { |
---|
[10847] | 341 | return findClass(first, second != NIL); |
---|
[10844] | 342 | } |
---|
[11488] | 343 | @Override |
---|
[10844] | 344 | public LispObject execute(LispObject first, LispObject second, |
---|
| 345 | LispObject third) |
---|
[12254] | 346 | |
---|
[10844] | 347 | { |
---|
[10847] | 348 | // FIXME Use environment! |
---|
| 349 | return findClass(first, second != NIL); |
---|
[10844] | 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 | { |
---|
[11488] | 357 | @Override |
---|
[10844] | 358 | public LispObject execute(LispObject first, LispObject second) |
---|
[12254] | 359 | |
---|
[10844] | 360 | { |
---|
[11754] | 361 | final Symbol name = checkSymbol(first); |
---|
[10844] | 362 | if (second == NIL) |
---|
| 363 | { |
---|
| 364 | removeClass(name); |
---|
| 365 | return second; |
---|
| 366 | } |
---|
[11754] | 367 | final LispClass c = checkClass(second); |
---|
[10844] | 368 | addClass(name, c); |
---|
| 369 | return second; |
---|
| 370 | } |
---|
| 371 | }; |
---|
| 372 | |
---|
[10843] | 373 | // ### subclassp |
---|
| 374 | private static final Primitive SUBCLASSP = |
---|
| 375 | new Primitive(Symbol.SUBCLASSP, "class") |
---|
[10423] | 376 | { |
---|
[11488] | 377 | @Override |
---|
[10843] | 378 | public LispObject execute(LispObject first, LispObject second) |
---|
[12254] | 379 | |
---|
[10843] | 380 | { |
---|
[11754] | 381 | final LispClass c = checkClass(first); |
---|
[10843] | 382 | return c.subclassp(second) ? T : NIL; |
---|
| 383 | } |
---|
[10423] | 384 | }; |
---|
[946] | 385 | } |
---|