1 21 22 package org.armedbear.lisp; 23 24 import java.util.ArrayList ; 25 import java.util.HashMap ; 26 import java.util.Iterator ; 27 import java.util.List ; 28 29 public final class Package extends LispObject 30 { 31 private String name; 32 33 private final HashMap internalSymbols = new HashMap (); 34 private final HashMap externalSymbols = new HashMap (); 35 private HashMap shadowingSymbols; 36 private ArrayList nicknames; 37 private final ArrayList useList = new ArrayList (); 38 private ArrayList usedByList = null; 39 40 public Package() 42 { 43 } 44 45 public Package(String name) 46 { 47 this.name = name; 48 } 49 50 public Package(String name, int size) 51 { 52 this.name = name; 53 } 54 55 public LispObject typeOf() 56 { 57 return Symbol.PACKAGE; 58 } 59 60 public LispClass classOf() 61 { 62 return BuiltInClass.PACKAGE; 63 } 64 65 public LispObject getDescription() 66 { 67 if (name != null) { 68 StringBuffer sb = new StringBuffer ("The "); 69 sb.append(name); 70 sb.append(" package"); 71 return new SimpleString(sb); 72 } 73 return new SimpleString("PACKAGE"); 74 } 75 76 public LispObject typep(LispObject type) throws ConditionThrowable 77 { 78 if (type == Symbol.PACKAGE) 79 return T; 80 if (type == BuiltInClass.PACKAGE) 81 return T; 82 return super.typep(type); 83 } 84 85 public final String getName() 86 { 87 return name; 88 } 89 90 public final List getNicknames() 91 { 92 return nicknames; 93 } 94 95 public final synchronized boolean delete() 96 { 97 if (name != null) { 98 Packages.deletePackage(this); 99 for (Iterator it = internalSymbols.values().iterator(); it.hasNext();) { 100 Symbol symbol = (Symbol) it.next(); 101 if (symbol.getPackage() == this) 102 symbol.setPackage(NIL); 103 it.remove(); 104 } 105 for (Iterator it = externalSymbols.values().iterator(); it.hasNext();) { 106 Symbol symbol = (Symbol) it.next(); 107 if (symbol.getPackage() == this) 108 symbol.setPackage(NIL); 109 it.remove(); 110 } 111 name = null; 112 nicknames = null; 113 return true; 114 } 115 return false; 116 } 117 118 public final synchronized void rename(String newName, LispObject newNicks) 119 throws ConditionThrowable 120 { 121 ArrayList arrayList = null; 122 while (newNicks != NIL) { 123 if (arrayList == null) 124 arrayList = new ArrayList (); 125 arrayList.add(javaString(newNicks.car())); 126 newNicks = newNicks.cdr(); 127 } 128 129 Packages.deletePackage(this); 131 132 name = newName; 134 nicknames = arrayList; 135 136 Packages.addPackage(this); 138 } 139 140 public synchronized Symbol findInternalSymbol(String name) 141 { 142 return (Symbol) internalSymbols.get(name); 143 } 144 145 public synchronized Symbol findExternalSymbol(String name) 146 { 147 return (Symbol) externalSymbols.get(name); 148 } 149 150 public synchronized Symbol findAccessibleSymbol(String name) 152 { 153 Symbol symbol = (Symbol) externalSymbols.get(name); 155 if (symbol != null) 156 return symbol; 157 symbol = (Symbol) internalSymbols.get(name); 158 if (symbol != null) 159 return symbol; 160 for (Iterator it = useList.iterator(); it.hasNext();) { 162 Package pkg = (Package ) it.next(); 163 symbol = pkg.findExternalSymbol(name); 164 if (symbol != null) 165 return symbol; 166 } 167 return null; 169 } 170 171 public synchronized LispObject findSymbol(String name) 172 throws ConditionThrowable 173 { 174 final LispThread thread = LispThread.currentThread(); 175 Symbol symbol = (Symbol) externalSymbols.get(name); 177 if (symbol != null) 178 return thread.setValues(symbol, Keyword.EXTERNAL); 179 symbol = (Symbol) internalSymbols.get(name); 180 if (symbol != null) 181 return thread.setValues(symbol, Keyword.INTERNAL); 182 for (Iterator it = useList.iterator(); it.hasNext();) { 184 Package pkg = (Package ) it.next(); 185 symbol = pkg.findExternalSymbol(name); 186 if (symbol != null) 187 return thread.setValues(symbol, Keyword.INHERITED); 188 } 189 return thread.setValues(NIL, NIL); 191 } 192 193 public synchronized void addSymbol(Symbol symbol) 195 { 196 Debug.assertTrue(symbol.getPackage() == this); 197 final String name = symbol.getName(); 198 Debug.assertTrue(name.equals("NIL")); 199 externalSymbols.put(symbol.getName(), symbol); 200 } 201 202 private synchronized Symbol addSymbol(String symbolName) 203 { 204 Symbol symbol = new Symbol(symbolName, this); 205 if (this == PACKAGE_KEYWORD) { 206 symbol.setSymbolValue(symbol); 207 symbol.setConstant(true); 208 externalSymbols.put(symbolName, symbol); 209 } else 210 internalSymbols.put(symbolName, symbol); 211 return symbol; 212 } 213 214 public synchronized Symbol addInternalSymbol(String symbolName) 215 { 216 Symbol symbol = new Symbol(symbolName, this); 217 internalSymbols.put(symbolName, symbol); 218 return symbol; 219 } 220 221 public synchronized Symbol addExternalSymbol(String symbolName) 222 { 223 Symbol symbol = new Symbol(symbolName, this); 224 externalSymbols.put(symbolName, symbol); 225 return symbol; 226 } 227 228 public synchronized void addInitialExports(String [] names) 229 { 230 for (int i = names.length; i-- > 0;) { 231 String symbolName = names[i]; 232 Debug.assertTrue(internalSymbols.get(symbolName) == null); 235 if (externalSymbols.get(symbolName) == null) 239 externalSymbols.put(symbolName, new Symbol(symbolName, this)); 240 } 241 } 242 243 public synchronized Symbol intern(String symbolName) 244 { 245 Symbol symbol = (Symbol) externalSymbols.get(symbolName); 247 if (symbol != null) 248 return symbol; 249 symbol = (Symbol) internalSymbols.get(symbolName); 250 if (symbol != null) 251 return symbol; 252 for (Iterator it = useList.iterator(); it.hasNext();) { 254 Package pkg = (Package ) it.next(); 255 symbol = pkg.findExternalSymbol(symbolName); 256 if (symbol != null) 257 return symbol; 258 } 259 return addSymbol(symbolName); 261 } 262 263 public synchronized Symbol intern(String name, LispThread thread) 264 { 265 Symbol symbol = (Symbol) externalSymbols.get(name); 267 if (symbol != null) 268 return (Symbol) thread.setValues(symbol, Keyword.EXTERNAL); 269 symbol = (Symbol) internalSymbols.get(name); 270 if (symbol != null) 271 return (Symbol) thread.setValues(symbol, Keyword.INTERNAL); 272 for (Iterator it = useList.iterator(); it.hasNext();) { 274 Package pkg = (Package ) it.next(); 275 symbol = pkg.findExternalSymbol(name); 276 if (symbol != null) 277 return (Symbol) thread.setValues(symbol, Keyword.INHERITED); 278 } 279 return (Symbol) thread.setValues(addSymbol(name), NIL); 281 } 282 283 public synchronized LispObject unintern(Symbol symbol) throws ConditionThrowable 284 { 285 final String symbolName = symbol.getName(); 286 final boolean shadow; 287 if (shadowingSymbols != null && shadowingSymbols.get(symbolName) == symbol) 288 shadow = true; 289 else 290 shadow = false; 291 if (shadow) { 292 Symbol sym = null; 295 for (Iterator it = useList.iterator(); it.hasNext();) { 296 Package pkg = (Package ) it.next(); 297 Symbol s = pkg.findExternalSymbol(symbolName); 298 if (s != null) { 299 if (sym == null) 300 sym = s; 301 else if (sym != s) { 302 StringBuffer sb = 303 new StringBuffer ("uninterning the symbol "); 304 sb.append(symbol.getQualifiedName()); 305 sb.append(" causes a name conflict between "); 306 sb.append(sym.getQualifiedName()); 307 sb.append(" and "); 308 sb.append(s.getQualifiedName()); 309 return signal(new PackageError(sb.toString())); 310 } 311 } 312 } 313 } 314 if (internalSymbols.get(symbolName) == symbol) { 316 internalSymbols.remove(symbolName); 317 } else if (externalSymbols.get(symbolName) == symbol) { 318 externalSymbols.remove(symbolName); 319 } else { 320 return NIL; 322 } 323 if (shadow) { 324 Debug.assertTrue(shadowingSymbols != null); 325 shadowingSymbols.remove(symbolName); 326 } 327 if (symbol.getPackage() == this) 328 symbol.setPackage(NIL); 329 return T; 330 } 331 332 public synchronized void importSymbol(Symbol symbol) throws ConditionThrowable 333 { 334 if (symbol.getPackage() == this) 335 return; Symbol sym = findAccessibleSymbol(symbol.getName()); 337 if (sym != null && sym != symbol) { 338 StringBuffer sb = new StringBuffer ("The symbol "); 339 sb.append(sym.getQualifiedName()); 340 sb.append(" is already accessible in package "); 341 sb.append(name); 342 sb.append('.'); 343 signal(new PackageError(sb.toString())); 344 return; 345 } 346 internalSymbols.put(symbol.getName(), symbol); 347 if (symbol.getPackage() == NIL) 348 symbol.setPackage(this); 349 } 350 351 public synchronized void export(Symbol symbol) throws ConditionThrowable 352 { 353 final String symbolName = symbol.getName(); 354 boolean added = false; 355 if (symbol.getPackage() != this) { 356 Symbol sym = findAccessibleSymbol(symbolName); 357 if (sym == null) { 358 StringBuffer sb = new StringBuffer ("The symbol "); 359 sb.append(symbol.getQualifiedName()); 360 sb.append(" is not accessible in package "); 361 sb.append(name); 362 sb.append('.'); 363 signal(new PackageError(sb.toString())); 364 return; 365 } 366 if (sym != symbol) { 367 StringBuffer sb = new StringBuffer ("The symbol "); 369 sb.append(sym.getQualifiedName()); 370 sb.append(" is already accessible in package "); 371 sb.append(name); 372 sb.append('.'); 373 signal(new PackageError(sb.toString())); 374 return; 375 } 376 internalSymbols.put(symbolName, symbol); 377 added = true; 378 } 379 if (added || internalSymbols.get(symbolName) == symbol) { 380 if (usedByList != null) { 381 for (Iterator it = usedByList.iterator(); it.hasNext();) { 382 Package pkg = (Package ) it.next(); 383 Symbol sym = pkg.findAccessibleSymbol(symbolName); 384 if (sym != null && sym != symbol) { 385 if (pkg.shadowingSymbols != null && 386 pkg.shadowingSymbols.get(symbolName) == sym) { 387 ; } else { 389 StringBuffer sb = new StringBuffer ("The symbol "); 390 sb.append(sym.getQualifiedName()); 391 sb.append(" is already accessible in package "); 392 sb.append(pkg.getName()); 393 sb.append('.'); 394 signal(new LispError(sb.toString())); 395 return; 396 } 397 } 398 } 399 } 400 internalSymbols.remove(symbolName); 402 externalSymbols.put(symbolName, symbol); 403 return; 404 } 405 if (externalSymbols.get(symbolName) == symbol) { 406 return; 408 } 409 StringBuffer sb = new StringBuffer ("The symbol "); 410 sb.append(symbol.getQualifiedName()); 411 sb.append(" is not accessible in package "); 412 sb.append(name); 413 sb.append('.'); 414 signal(new PackageError(sb.toString())); 415 } 416 417 public synchronized void unexport(Symbol symbol) throws ConditionThrowable 418 { 419 final String symbolName = symbol.getName(); 420 if (symbol.getPackage() == this) { 421 if (externalSymbols.get(symbolName) == symbol) { 422 externalSymbols.remove(symbolName); 423 internalSymbols.put(symbolName, symbol); 424 } 425 } else { 426 for (Iterator it = useList.iterator(); it.hasNext();) { 428 Package pkg = (Package ) it.next(); 429 if (pkg.findExternalSymbol(symbolName) == symbol) 430 return; } 432 StringBuffer sb = new StringBuffer ("the symbol "); 433 sb.append(symbol.getQualifiedName()); 434 sb.append(" is not accessible in package "); 435 sb.append(name); 436 signal(new PackageError(sb.toString())); 437 } 438 } 439 440 public synchronized void shadow(String symbolName) throws ConditionThrowable 441 { 442 Symbol symbol = (Symbol) externalSymbols.get(symbolName); 443 if (symbol != null) 444 return; 445 symbol = (Symbol) internalSymbols.get(symbolName); 446 if (symbol != null) 447 return; 448 if (shadowingSymbols != null) { 449 if (shadowingSymbols.get(symbolName) != null) 450 return; 451 } else 452 shadowingSymbols = new HashMap (); 453 454 symbol = new Symbol(symbolName, this); 455 internalSymbols.put(symbolName, symbol); 456 shadowingSymbols.put(symbolName, symbol); 457 } 458 459 public synchronized void shadowingImport(Symbol symbol) throws ConditionThrowable 460 { 461 LispObject where = NIL; 462 final String symbolName = symbol.getName(); 463 Symbol sym = (Symbol) externalSymbols.get(symbolName); 464 if (sym != null) { 465 where = Keyword.EXTERNAL; 466 } else { 467 sym = (Symbol) internalSymbols.get(symbolName); 468 if (sym != null) { 469 where = Keyword.INTERNAL; 470 } else { 471 for (Iterator it = useList.iterator(); it.hasNext();) { 473 Package pkg = (Package ) it.next(); 474 sym = pkg.findExternalSymbol(symbolName); 475 if (sym != null) { 476 where = Keyword.INHERITED; 477 break; 478 } 479 } 480 } 481 } 482 if (sym != null) { 483 if (where == Keyword.INTERNAL || where == Keyword.EXTERNAL) { 484 if (sym != symbol) { 485 if (shadowingSymbols != null) 486 shadowingSymbols.remove(symbolName); 487 unintern(sym); 488 } 489 } 490 } 491 internalSymbols.put(symbolName, symbol); 492 if (shadowingSymbols == null) 493 shadowingSymbols = new HashMap (); 494 Debug.assertTrue(shadowingSymbols.get(symbolName) == null); 495 shadowingSymbols.put(symbolName, symbol); 496 } 497 498 public void usePackage(Package pkg) 500 { 501 if (!useList.contains(pkg)) { 502 useList.add(pkg); 503 if (pkg.usedByList != null) 505 Debug.assertTrue(!pkg.usedByList.contains(this)); 506 if (pkg.usedByList == null) 507 pkg.usedByList = new ArrayList (); 508 pkg.usedByList.add(this); 509 } 510 } 511 512 public void unusePackage(Package pkg) 513 { 514 if (useList.contains(pkg)) { 515 useList.remove(pkg); 516 Debug.assertTrue(pkg.usedByList != null); 517 Debug.assertTrue(pkg.usedByList.contains(this)); 518 pkg.usedByList.remove(this); 519 } 520 } 521 522 public final void addNickname(String s) throws ConditionThrowable 523 { 524 Packages.addNickname(this, s); 526 527 if (nicknames != null) { 528 if (nicknames.contains(s)) 529 return; } else 531 nicknames = new ArrayList (); 532 533 nicknames.add(s); 534 } 535 536 public String getNickname() 537 { 538 if (nicknames != null && nicknames.size() > 0) 539 return (String ) nicknames.get(0); 540 return null; 541 } 542 543 public LispObject packageNicknames() 544 { 545 LispObject list = NIL; 546 if (nicknames != null) { 547 for (int i = nicknames.size(); i-- > 0;) { 548 String nickname = (String ) nicknames.get(i); 549 list = new Cons(new SimpleString(nickname), list); 550 } 551 } 552 return list; 553 } 554 555 public LispObject getUseList() 556 { 557 LispObject list = NIL; 558 for (Iterator it = useList.iterator(); it.hasNext();) { 559 Package pkg = (Package ) it.next(); 560 list = new Cons(pkg, list); 561 } 562 return list; 563 } 564 565 public boolean uses(LispObject pkg) 566 { 567 return useList.contains(pkg); 568 } 569 570 public LispObject getUsedByList() 571 { 572 LispObject list = NIL; 573 if (usedByList != null) { 574 for (Iterator it = usedByList.iterator(); it.hasNext();) { 575 Package pkg = (Package ) it.next(); 576 list = new Cons(pkg, list); 577 } 578 } 579 return list; 580 } 581 582 public LispObject getShadowingSymbols() 583 { 584 LispObject list = NIL; 585 if (shadowingSymbols != null) { 586 for (Iterator it = shadowingSymbols.values().iterator(); it.hasNext();) { 587 Symbol symbol = (Symbol) it.next(); 588 list = new Cons(symbol, list); 589 } 590 } 591 return list; 592 } 593 594 public synchronized List getExternalSymbols() 595 { 596 ArrayList list = new ArrayList (); 597 for (Iterator it = externalSymbols.values().iterator(); it.hasNext();) { 598 Symbol symbol = (Symbol) it.next(); 599 list.add(symbol); 600 } 601 return list; 602 } 603 604 public synchronized List getAccessibleSymbols() 605 { 606 ArrayList list = new ArrayList (); 607 for (Iterator it = internalSymbols.values().iterator(); it.hasNext();) { 608 Symbol symbol = (Symbol) it.next(); 609 list.add(symbol); 610 } 611 for (Iterator it = externalSymbols.values().iterator(); it.hasNext();) { 612 Symbol symbol = (Symbol) it.next(); 613 list.add(symbol); 614 } 615 for (Iterator packageIter = useList.iterator(); packageIter.hasNext();) { 616 Package pkg = (Package ) packageIter.next(); 617 for (Iterator it = pkg.externalSymbols.values().iterator(); it.hasNext();) { 618 Symbol symbol = (Symbol) it.next(); 619 if (shadowingSymbols == null || shadowingSymbols.get(symbol.getName()) == null) 620 list.add(symbol); 621 } 622 } 623 return list; 624 } 625 626 public synchronized LispObject PACKAGE_INTERNAL_SYMBOLS() 627 { 628 LispObject list = NIL; 629 for (Iterator it = internalSymbols.values().iterator(); it.hasNext();) { 630 Symbol symbol = (Symbol) it.next(); 631 list = new Cons(symbol, list); 632 } 633 return list; 634 } 635 636 public synchronized LispObject PACKAGE_EXTERNAL_SYMBOLS() 637 { 638 LispObject list = NIL; 639 for (Iterator it = externalSymbols.values().iterator(); it.hasNext();) { 640 Symbol symbol = (Symbol) it.next(); 641 list = new Cons(symbol, list); 642 } 643 return list; 644 } 645 646 public synchronized LispObject PACKAGE_INHERITED_SYMBOLS() 647 { 648 LispObject list = NIL; 649 for (Iterator packageIter = useList.iterator(); packageIter.hasNext();) { 650 Package pkg = (Package ) packageIter.next(); 651 for (Iterator it = pkg.externalSymbols.values().iterator(); it.hasNext();) { 652 Symbol symbol = (Symbol) it.next(); 653 if (shadowingSymbols != null && shadowingSymbols.get(symbol.getName()) != null) 654 continue; 655 if (externalSymbols.get(symbol.getName()) == symbol) 656 continue; 657 list = new Cons(symbol, list); 658 } 659 } 660 return list; 661 } 662 663 public synchronized LispObject getSymbols() 664 { 665 LispObject list = NIL; 666 for (Iterator it = internalSymbols.values().iterator(); it.hasNext();) { 667 Symbol symbol = (Symbol) it.next(); 668 list = new Cons(symbol, list); 669 } 670 for (Iterator it = externalSymbols.values().iterator(); it.hasNext();) { 671 Symbol symbol = (Symbol) it.next(); 672 list = new Cons(symbol, list); 673 } 674 return list; 675 } 676 677 public synchronized Symbol[] symbols() 678 { 679 Symbol[] array = new Symbol[internalSymbols.size() + externalSymbols.size()]; 680 int i = 0; 681 for (Iterator it = internalSymbols.values().iterator(); it.hasNext();) { 682 Symbol symbol = (Symbol) it.next(); 683 array[i++] = symbol; 684 } 685 for (Iterator it = externalSymbols.values().iterator(); it.hasNext();) { 686 Symbol symbol = (Symbol) it.next(); 687 array[i++] = symbol; 688 } 689 return array; 690 } 691 692 public String writeToString() throws ConditionThrowable 693 { 694 if (_PRINT_FASL_.symbolValue() != NIL && name != null) { 695 StringBuffer sb = new StringBuffer ("#.(FIND-PACKAGE \""); 696 sb.append(name); 697 sb.append("\")"); 698 return sb.toString(); 699 } else if (name != null) { 700 StringBuffer sb = new StringBuffer ("#<PACKAGE \""); 701 sb.append(name); 702 sb.append("\">"); 703 return sb.toString(); 704 } else 705 return unreadableString("PACKAGE"); 706 } 707 } 708 | Popular Tags |