Overview
This topic discusses how the Common Lisp
PackageSystem is implemented in
CLforJava. A package establishes a mapping from names to symbols. At any given time, one package is current, and this package is used by the Lisp reader in translating strings into symbols. The value of the global
variable *package* is the current package. Each package has a name, which is a string. It is assigned when the package is interned or created. There is a single namespace for packages;
CLforJava uses a
HashMap? named OBARRAY for this storing purpose.
The mappings in a package are divided into two classes, external and internal, therefore a package can have internal and external symbols. A name in a package referers to one symbol or none. But if it does refer to a symbol then it is either an internal symbol or an external symbol, but not both. External symbols are part of the package's public interface to other packages. Symbols become external symbols if they have been put on the packages export list.
CommonLisp standardized packages are COMMON-LISP, COMMON-LISP-USER, KEYWORD, SYSTEM, and KEYWORD.
References
Current Implementation
The current implementation uses only the COMMON-LISP package, which contains the primitives of the
CommonLisp system as defined by the
HyperSpec? specification. Its external symbols include all of the defined names (except for defined names in the KEYWORD package) that are present in the Common Lisp system, such as car, cdr, cons,
package, etc.
Package Interface
public interface Package extends Atom, java.util.Map {
/** The singleton that holds the Packages */
public static final Map OBARRAY = new HashMap();
/** a list associated with each package which determines
what other packages are currently being used by that package.
*/
public Map USES = new HashMap();
/** a list of other packages that use package*/
public Map USE_BY = new HashMap();
/** */
public Map SHADOW_LIST = new HashMap();
/** The instance of the Common-Lisp Package. */
public static final Package CommonLisp = Package.Factory.newInstance("COMMON-LISP");
/** The instance of the Lisp-User Package */
public static final Package CommonLispUser = Package.Factory.newInstance("COMMON-LISP-USER");
/** The instance of the Keyword Package */
public static final Package Keyword = lisp.system.KeywordPackageImpl.KeywordPackage;
/** The instance of the System Package */
public static final Package System = Package.Factory.newInstance("SYSTEM");
/** The instance of the Extensions Package */
public static final Package Extensions = Package.Factory.newInstance("EXTENSIONS");
/** The instance of the typeName Symbol */
public static final Symbol typeName = (Symbol)CommonLisp.intern("PACKAGE").get(0);;
/** Factory class for creating packages. If the singleton that holds
* the Package contains a package with a specified namne it is returned.
* Else if creates it and returns it.
*
*/
public class Factory {
public static final Package newInstance(java.lang.String name) {
if (OBARRAY.containsKey(name)) {
return (Package)OBARRAY.get(name);
}
else {
Package thePackage = new lisp.system.PackageImpl(name);
OBARRAY.put(name, thePackage);
return thePackage;
}
}
}
/** intern method looks up a symbol and if found returns the symbol and
* 'T', else if it returns null it creates that symbol with that name and return it
* along with the value 'NIL' and setting its home package.
* @param symbolName name of the Symbol
* @return instance of MultiVal
*/
public MultipleValue intern(java.lang.String symbolName);
/** unintern method removes the symbol from the package it is present,
* and from the packages shadowing list if it present there.
* If the package is the home package for the symbol, the
* symbol is made to have no home package.
* If the symbol is removed, T is returned.
* Else if the symbol is not in the package NIL is returned.
* @param theSymbol the symbol being unintern
* @return instance of a Object
*/
public Object unintern(Symbol theSymbol);
/** export method makes one or more symbols that are
*accessible in a package be external symbols of that package.
*If the symbol is already accessible as an external symbol, the
*method has no effect. If the symbol exists as an internal symbol,
*the method changes the symbol to external status. If the symbol
*exists as an internal symbol, but through the use-package method, the
*method imports the symbol into the package, then the method changes the
*symbol to external status. Else, the symbol is not accessible in the package,
*the method throws an error of type package error and prompts the user
*to import the symbol. Returns T on a successful export.
*@param symbolList - list of symbols to be exported
*@return instance of an Object
*/
public Object export(List symbolList);
/** import method makes one or more symbols that are
*accessible in a specified package be internal symbols of an importing package.
*If the symbol is already in the importing package the method has
*no effect. If the symbol exists as an internal symbol the
*importing symbol may replace the current symbol, be placed on the shadow
*list, or be ignored.
*Returns T on a successful export.
*@param symbolList - list of symbols to be exported
*@return instance of an Object
*/
public Object import(List symbolList);
/**The shadow method places a symbol or symbols on a package shadowing symbols list.
*If no package is specified the symbol is added to the current package. If a
*symbol of the same name is already accessible in the package, the shadow method
*will determine whether it is directly present in the package or accessible through
*inheritance. If directly present, the symbol is placed on the shadowing symbols list.
*If inherited, a new internal symbol is created and placed on the shadowing symbols list.
*If no symbol is accessible or present in the package one is created, made internal and
*placed on the shadowing symbols list.
*@param symbol-names --- string designators
*@param package --- a package designator default is the current package
*@return Symbol T
*/
public Symbol shadow(List symbolList, Package package);
/**The packageShadowingSymbols method takes a package
*designator as a parameter and returns the symbols
*contained in the package’s Shadow_List. If the
*Shadow_List contains no symbols the method returns
*NIL.
*@return an instance of MultipleValue
*/
public MultipleValue packageShadowingSymbols ();
/** findSymbol method finds a symbol and return it from the symbol array
* @param symbolName of the Symbol
* @return instance of a Symbol
*/
public Symbol findSymbol(java.lang.String symbolName);
/** deletePackage method removes specified Packgae name.
* @param name of the Package
* @return instance of a boolean */
public boolean deletePackage(java.lang.String name);
/** getName method returns the name of the Package
*@return a string that is the name of the Package
*/
public java.lang.String getName();
/** use-package causes a package to inherit all the external symbols of packages-to-use list.
* The inherited symbols become accessible as internal symbols of package.
*@param packagesToUse -- the List of packages to use.
*@return Symbol T
*/
public Object usePackage(List packagesToUse)
}
Discussions
Links to Blog issues
Status:
Release Level:
Open bug count:
Test Suites
Links to JUnit results
--
JerryBoetje - 12 Jul 2003